BP_REST_Topics_Actions_Endpoint
Topics Actions endpoints.
Description
Source
File: bp-forums/classes/class-bp-rest-topics-actions-endpoint.php
class BP_REST_Topics_Actions_Endpoint extends BP_REST_Topics_Endpoint { /** * BP_REST_Groups_Endpoint Instance. * * @var BP_REST_Forums_Endpoint */ protected $forum_endpoint; /** * Constructor. * * @since 0.1.0 */ public function __construct() { $this->namespace = bp_rest_namespace() . '/' . bp_rest_version(); $this->rest_base = 'topics'; $this->forum_endpoint = new BP_REST_Forums_Endpoint(); } /** * Register the component routes. * * @since 0.1.0 */ public function register_routes() { register_rest_route( $this->namespace, '/' . $this->rest_base . '/merge/(?P<id>[\d]+)', array( 'args' => array( 'id' => array( 'description' => __( 'A unique numeric ID for the topic.', 'buddyboss' ), 'type' => 'integer', 'required' => true, ), 'destination_id' => array( 'description' => __( 'A unique numeric ID for the destination topic.', 'buddyboss' ), 'type' => 'integer', 'required' => true, ), 'subscribers' => array( 'description' => __( 'Whether to migrate subscriptions or not.', 'buddyboss' ), 'type' => 'boolean', 'default' => true, ), 'favorites' => array( 'description' => __( 'Whether to migrate favorites or not.', 'buddyboss' ), 'type' => 'boolean', 'default' => true, ), 'tags' => array( 'description' => __( 'Whether to migrate tags or not.', 'buddyboss' ), 'type' => 'boolean', 'default' => true, ), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'merge_item' ), 'permission_callback' => array( $this, 'merge_item_permissions_check' ), ), 'schema' => array( $this, 'get_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/split/(?P<id>[\d]+)', array( 'args' => array( 'id' => array( 'description' => __( 'A unique numeric ID for the topic.', 'buddyboss' ), 'type' => 'integer', 'required' => true, ), 'reply_id' => array( 'description' => __( 'A unique numeric ID for the topic\'s reply.', 'buddyboss' ), 'type' => 'integer', 'required' => true, ), 'split_option' => array( 'description' => __( 'Choose a valid split option.', 'buddyboss' ), 'type' => 'string', 'required' => true, 'enum' => array( 'reply', 'existing' ), ), 'new_destination_title' => array( 'description' => __( 'New Topic title for the split with option reply.', 'buddyboss' ), 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg', ), 'destination_id' => array( 'description' => __( 'A unique numeric ID for the destination topic.', 'buddyboss' ), 'type' => 'integer', ), 'subscribers' => array( 'description' => __( 'Whether to migrate subscriptions or not.', 'buddyboss' ), 'type' => 'boolean', 'default' => true, ), 'favorites' => array( 'description' => __( 'Whether to migrate favorites or not.', 'buddyboss' ), 'type' => 'boolean', 'default' => true, ), 'tags' => array( 'description' => __( 'Whether to migrate tags or not.', 'buddyboss' ), 'type' => 'boolean', 'default' => true, ), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'split_item' ), 'permission_callback' => array( $this, 'split_item_permissions_check' ), ), 'schema' => array( $this, 'get_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/action/(?P<id>[\d]+)', array( 'args' => array( 'id' => array( 'description' => __( 'A unique numeric ID for the topic.', 'buddyboss' ), 'type' => 'integer', 'required' => true, ), 'action' => array( 'description' => __( 'Action name to perform on the topic', 'buddyboss' ), 'type' => 'string', 'required' => true, 'enum' => array( 'favorite', 'subscribe', 'close', 'sticky', 'super_sticky', 'spam', 'trash', ), 'sanitize_callback' => 'sanitize_key', 'validate_callback' => 'rest_validate_request_arg', ), 'value' => array( 'description' => __( 'Value for the action on topic.', 'buddyboss' ), 'type' => 'boolean', 'sanitize_callback' => 'rest_sanitize_boolean', 'validate_callback' => 'rest_validate_request_arg', ), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'action_items' ), 'permission_callback' => array( $this, 'action_items_permissions_check' ), ), 'schema' => array( $this, 'get_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/dropdown/(?P<id>[\d]+)', array( 'args' => array( 'id' => array( 'description' => __( 'A unique numeric ID for the topic.', 'buddyboss' ), 'type' => 'integer', 'required' => true, ), 'page' => array( 'required' => false, 'default' => 1, 'description' => __( 'Current page of the collection.', 'buddyboss' ), 'type' => 'integer', 'sanitize_callback' => 'absint', 'validate_callback' => 'rest_validate_request_arg', ), 'per_page' => array( 'required' => false, 'default' => 10, 'description' => __( 'Maximum number of items to be returned in result set.', 'buddyboss' ), 'type' => 'integer', 'sanitize_callback' => 'absint', 'maximum' => 9999999, 'validate_callback' => 'rest_validate_request_arg', ), ), array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'dropdown_items' ), 'permission_callback' => array( $this, 'dropdown_items_permissions_check' ), ), 'schema' => array( $this, 'get_dropdown_item_schema' ), ) ); } /** * Merge Topic * * @param WP_REST_Request $request Full details about the request. * * @return WP_REST_Response | WP_Error * @since 0.1.0 * * @api {POST} /wp-json/buddyboss/v1/topics/merge/:id Merge Topic * @apiName MergeBBPTopic * @apiGroup Forum Topics * @apiDescription Merge Topic * @apiVersion 1.0.0 * @apiPermission LoggedInUser * @apiParam {Number} id A unique numeric ID for the topic. * @apiParam {Number} destination_id A unique numeric ID for the destination topic. * @apiParam {Boolean} [subscribers=true] Whether to migrate subscriptions or not. * @apiParam {Boolean} [favorites=true] Whether to migrate favorites or not. * @apiParam {Boolean} [tags=true] Whether to migrate tags or not. */ public function merge_item( $request ) { // Define local variable(s). $source_topic_id = 0; $destination_topic_id = 0; $source_topic = 0; $destination_topic = 0; $subscribers = array(); $favoriters = array(); $replies = array(); // Topic id. if ( empty( $request['id'] ) ) { return new WP_Error( 'bp_rest_topic_invalid_id', __( 'Invalid topic ID.', 'buddyboss' ), array( 'status' => 404, ) ); } else { $source_topic_id = (int) $request['id']; } // Source topic not found. $source_topic = bbp_get_topic( $source_topic_id ); if ( empty( $source_topic ) ) { return new WP_Error( 'bp_rest_bbp_merge_topic_source_not_found', __( 'The topic you want to merge was not found.', 'buddyboss' ), array( 'status' => 404, ) ); } // Cannot edit source topic. if ( ! current_user_can( 'edit_topic', $source_topic->ID ) ) { return new WP_Error( 'bp_rest_bbp_merge_topic_source_permission', __( 'Sorry, You do not have permission to edit the source topic.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } /** Destination Topic */ // Topic id. if ( empty( $request['destination_id'] ) ) { return new WP_Error( 'bp_rest_bbp_merge_topic_destination_id', __( 'Sorry, Destination discussion ID not found.', 'buddyboss' ), array( 'status' => 404, ) ); } else { $destination_topic_id = (int) $request['destination_id']; } // Destination topic not found. $destination_topic = bbp_get_topic( $destination_topic_id ); if ( empty( $destination_topic ) ) { return new WP_Error( 'bp_rest_bbp_merge_topic_destination_not_found', __( 'Sorry, The discussion you want to merge to was not found.', 'buddyboss' ), array( 'status' => 404, ) ); } // Cannot edit destination topic. if ( ! current_user_can( 'edit_topic', $destination_topic->ID ) ) { return new WP_Error( 'bp_rest_bbp_merge_topic_destination_permission', __( 'Sorry, You do not have the permissions to edit the destination discussion.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } /** No Errors */ // Update counts, etc... do_action( 'bbp_merge_topic', $destination_topic->ID, $source_topic->ID ); /** Date Check */ // Check if the destination topic is older than the source topic. if ( strtotime( $source_topic->post_date ) < strtotime( $destination_topic->post_date ) ) { // Set destination topic post_date to 1 second before source topic. $destination_post_date = gmdate( 'Y-m-d H:i:s', strtotime( $source_topic->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 */ // Get subscribers from source topic. $subscribers = bbp_get_topic_subscribers( $source_topic->ID ); // Remove the topic from everybody's subscriptions. if ( ! empty( $subscribers ) ) { // Loop through each user. foreach ( (array) $subscribers as $subscriber ) { // Shift the subscriber if told to. if ( ! empty( $request['subscribers'] ) && ( true === $request['subscribers'] ) && bbp_is_subscriptions_active() ) { bbp_add_user_subscription( $subscriber, $destination_topic->ID ); } // Remove old subscription. bbp_remove_user_subscription( $subscriber, $source_topic->ID ); } } /** Favorites */ // Get favoriters from source topic. $favoriters = bbp_get_topic_favoriters( $source_topic->ID ); // Remove the topic from everybody's favorites. if ( ! empty( $favoriters ) ) { // Loop through each user. foreach ( (array) $favoriters as $favoriter ) { // Shift the favoriter if told to. if ( ! empty( $request['favorites'] ) && true === $request['favorites'] ) { bbp_add_user_favorite( $favoriter, $destination_topic->ID ); } // Remove old favorite. bbp_remove_user_favorite( $favoriter, $source_topic->ID ); } } /** 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' ) ); // Tags to possibly merge. if ( ! empty( $source_topic_tags ) && ! is_wp_error( $source_topic_tags ) ) { // Shift the tags if told to. if ( ! empty( $request['tags'] ) && ( true === $request['tags'] ) ) { wp_set_post_terms( $destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true ); } // Delete the tags from the source topic. wp_delete_object_term_relationships( $source_topic->ID, bbp_get_topic_tag_tax_id() ); } /** Source Topic */ // Status. bbp_open_topic( $source_topic->ID ); // Sticky. bbp_unstick_topic( $source_topic->ID ); // Get the replies of the source topic. $replies = (array) get_posts( array( 'post_parent' => $source_topic->ID, 'post_type' => bbp_get_reply_post_type(), 'posts_per_page' => - 1, 'order' => 'ASC', ) ); // Prepend the source topic to its replies array for processing. array_unshift( $replies, $source_topic ); if ( ! empty( $replies ) ) { /** Merge Replies */ // 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' => sprintf( /* translators: Topic Title. */ __( 'Reply To: %s', 'buddyboss' ), $destination_topic->post_title ), 'post_name' => false, 'post_type' => bbp_get_reply_post_type(), 'post_parent' => $destination_topic->ID, 'guid' => '', ) ); // 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 to values. $reply_to = bbp_get_reply_to( $reply->ID ); if ( empty( $reply_to ) ) { bbp_update_reply_to( $reply->ID, $source_topic->ID ); } // Do additional actions per merged reply. do_action( 'bbp_merged_topic_reply', $reply->ID, $destination_topic->ID ); } } /** Successful Merge */ // Update topic's last meta data. bbp_update_topic_last_reply_id( $destination_topic->ID ); bbp_update_topic_last_active_id( $destination_topic->ID ); bbp_update_topic_last_active_time( $destination_topic->ID ); // Send the post parent of the source topic as it has been shifted. // (possibly to a new forum) so we need to update the counts of the. // old forum as well as the new one. do_action( 'bbp_merged_topic', $destination_topic->ID, $source_topic->ID, $source_topic->post_parent ); /** * Fires after a list of topic is merged via the REST API. * * @param array $destination_topic Destination topic. * @param array $source_topic Source topic. * @param WP_REST_Request $request The request sent to the API. * * @since 0.1.0 */ do_action( 'bp_rest_topic_get_item', $destination_topic, $source_topic, $request ); return $this->get_item( array( 'id' => $destination_topic->ID, 'context' => 'view', ) ); } /** * Check if a given request has access to merge a topic. * * @param WP_REST_Request $request Full data about the request. * * @return bool|WP_Error * @since 0.1.0 */ public function merge_item_permissions_check( $request ) { $retval = true; if ( ! is_user_logged_in() ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you need to be logged in to update a topic.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } if ( true === $retval ) { $retval = $this->get_item_permissions_check( $request ); } if ( true === $retval ) { if ( ! current_user_can( 'edit_topic', $request['id'] ) ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you are not allowed to merge this topic.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } } /** * Filter the topic `merge_item` permissions check. * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. * * @since 0.1.0 */ return apply_filters( 'bp_rest_topic_merge_item_permissions_check', $retval, $request ); } /** * Split Topic * * @param WP_REST_Request $request Full details about the request. * * @return WP_REST_Response | WP_Error * @since 0.1.0 * * @api {POST} /wp-json/buddyboss/v1/topics/split/:id Split Topic * @apiName SplitBBPTopic * @apiGroup Forum Topics * @apiDescription Split Topic * @apiVersion 1.0.0 * @apiPermission LoggedInUser * @apiParam {Number} id A unique numeric ID for the topic. * @apiParam {Number} reply_id A unique numeric ID for the topic's reply. * @apiParam {String=reply,existing} split_option Choose a valid split option. * @apiParam {String} [new_destination_title] New Topic title for the split with option reply. * @apiParam {Number} [destination_id] A unique numeric ID for the destination topic. * @apiParam {Boolean} [subscribers=true] Whether to migrate subscriptions or not. * @apiParam {Boolean} [favorites=true] Whether to migrate favorites or not. * @apiParam {Boolean} [tags=true] Whether to migrate tags or not. */ public function split_item( $request ) { global $wpdb; // Prevent debug notices. $split_option = false; /** Split Reply */ if ( empty( $request['reply_id'] ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_reply_id', __( 'Reply ID to split the topic from not found!', 'buddyboss' ), array( 'status' => 404, ) ); } else { $from_reply_id = (int) $request['reply_id']; } $from_reply = bbp_get_reply( $from_reply_id ); // Reply exists. if ( empty( $from_reply ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_r_not_found', __( 'The reply you want to split from was not found.', 'buddyboss' ), array( 'status' => 404, ) ); } /** Topic to Split */ // Get the topic being split. $source_topic = bbp_get_topic( $from_reply->post_parent ); // No topic. if ( empty( $source_topic ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_source_not_found', __( 'The topic you want to split was not found.', 'buddyboss' ), array( 'status' => 404, ) ); } // Use cannot edit topic. if ( ! current_user_can( 'edit_topic', $source_topic->ID ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_source_permission', __( 'Sorry, You do not have the permissions to edit the source discussion.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } // How to Split. if ( ! empty( $request['split_option'] ) ) { $split_option = (string) trim( $request['split_option'] ); } if ( empty( $split_option ) || ! in_array( $split_option, array( 'existing', 'reply' ), true ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_option', __( 'Sorry, You need to choose a valid split option.', 'buddyboss' ), array( 'status' => 404, ) ); // Valid Split Option. } else { // What kind of split. switch ( $split_option ) { // Into an existing topic. case 'existing': // Get destination topic id. if ( empty( $request['destination_id'] ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_destination_id', __( 'Sorry, Destination discussion ID not found!', 'buddyboss' ), array( 'status' => 404, ) ); } else { $destination_topic_id = (int) $request['destination_id']; } // Get the destination topic. $destination_topic = bbp_get_topic( $destination_topic_id ); // No destination topic. if ( empty( $destination_topic ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_destination_not_found', __( 'Sorry, The discussion you want to split to was not found!', 'buddyboss' ), array( 'status' => 404, ) ); } // User cannot edit the destination topic. if ( ! current_user_can( 'edit_topic', $destination_topic->ID ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_destination_permission', __( 'Sorry, You do not have the permissions to edit the destination discussion!', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } break; // 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( $request['new_destination_title'] ) ) { $destination_topic_title = esc_attr( wp_strip_all_tags( $request['new_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 ) ) { return new WP_Error( 'bp_rest_bbp_split_topic_destination_reply', __( 'Sorry, There was a problem converting the reply into the discussion. Please try again.', 'buddyboss' ), array( 'status' => 404, ) ); } // User cannot publish posts. } else { return new WP_Error( 'bp_rest_bbp_split_topic_destination_permission', __( 'Sorry, You do not have the permissions to create new topics. The reply could not be converted into a discussion.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } break; } } /** 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 = gmdate( '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( $request['subscribers'] ) && true === $request['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( $request['favorites'] ) && ( true === $request['favorites'] ) ) { // 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( $request['tags'] ) && ( true === $request['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. // phpcs:ignore $replies = (array) $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_date >= %s AND {$wpdb->posts}.post_parent = %d AND {$wpdb->posts}.post_type = %s ORDER BY {$wpdb->posts}.post_date ASC", $from_reply->post_date, $source_topic->ID, bbp_get_reply_post_type() ) ); // Make sure there are replies to loop through. if ( ! empty( $replies ) && ! is_wp_error( $replies ) ) { // Calculate starting point for reply positions. switch ( $split_option ) { // Get topic reply count for existing topic. case 'existing': $reply_position = bbp_get_topic_reply_count( $destination_topic->ID ); break; // Account for new lead topic. case 'reply': $reply_position = 1; break; } // Save reply ids. $reply_ids = array(); // Change the post_parent of each reply to the destination topic id. foreach ( $replies as $reply ) { // Bump the reply position each iteration through the loop. $reply_position++; // Update the reply. wp_update_post( array( 'ID' => $reply->ID, 'post_title' => sprintf( /* translators: Topic Title. */ __( 'Reply To: %s', 'buddyboss' ), $destination_topic->post_title ), 'post_name' => false, // will be automatically generated. 'post_parent' => $destination_topic->ID, 'menu_order' => $reply_position, '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 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, true ) ) { 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 ); /** * Fires after a list of topic is split via the REST API. * * @param array $from_reply Reply ID to start split from. * @param array $source_topic Source topic. * @param array $destination_topic Destination topic. * @param WP_REST_Request $request The request sent to the API. * * @since 0.1.0 */ do_action( 'bp_rest_split_get_item', $from_reply, $source_topic, $destination_topic, $request ); return $this->get_item( array( 'id' => $destination_topic->ID, 'context' => 'view', ) ); } /** * Check if a given request has access to merge a topic. * * @param WP_REST_Request $request Full data about the request. * * @return bool|WP_Error * @since 0.1.0 */ public function split_item_permissions_check( $request ) { $retval = true; if ( ! is_user_logged_in() ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you need to be logged in to split a topic.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } if ( true === $retval ) { $retval = $this->get_item_permissions_check( $request ); } if ( true === $retval ) { if ( ! current_user_can( 'edit_topic', $request['id'] ) ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you are not allowed to split this topic.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } } /** * Filter the topic `split_item` permissions check. * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. * * @since 0.1.0 */ return apply_filters( 'bp_rest_topic_split_item_permissions_check', $retval, $request ); } /** * Actions on Topic * * @param WP_REST_Request $request Full details about the request. * * @return WP_REST_Response | WP_Error * @since 0.1.0 * * @api {POST} /wp-json/buddyboss/v1/topics/action/:id Topic Actions * @apiName ActionBBPTopic * @apiGroup Forum Topics * @apiDescription Actions on Topic * @apiVersion 1.0.0 * @apiPermission LoggedInUser * @apiParam {Number} id A unique numeric ID for the topic. * @apiParam {String=favorite,subscribe,close,sticky,super_sticky,spam,trash} action Action name to perform on the topic. * @apiParam {Boolean} value Value for the action on topic. */ public function action_items( $request ) { $action = $request->get_param( 'action' ); $value = $request->get_param( 'value' ); $topic_id = $request->get_param( 'id' ); $user_id = bbp_get_user_id( 0, true, true ); $retval = ''; switch ( $action ) { case 'favorite': $retval = $this->rest_update_favorite( $topic_id, $value, $user_id ); break; case 'subscribe': $retval = $this->rest_update_subscribe( $topic_id, $value, $user_id ); break; case 'close': $retval = $this->rest_update_close( $topic_id, $value ); break; case 'sticky': case 'super_sticky': $retval = $this->rest_update_sticky( $topic_id, $action, $value ); break; case 'spam': $retval = $this->rest_update_spam( $topic_id, $value ); break; case 'trash': $retval = $this->rest_update_trash( $topic_id, $value ); break; } if ( is_wp_error( $retval ) ) { return $retval; } return $this->get_item( array( 'id' => $topic_id, 'context' => 'view', ) ); } /** * Check if a given request has access to perform an action on topic. * * @param WP_REST_Request $request Full data about the request. * * @return bool|WP_Error * @since 0.1.0 */ public function action_items_permissions_check( $request ) { $retval = true; if ( ! is_user_logged_in() ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you need to be logged in to perform the action on the topic.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } if ( true === $retval ) { $retval = $this->get_item_permissions_check( $request ); } /** * Filter the topic `action_item` permissions check. * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. * * @since 0.1.0 */ return apply_filters( 'bp_rest_topic_action_item_permissions_check', $retval, $request ); } /** * Topic's Dropdown * * @param WP_REST_Request $request Full details about the request. * * @return WP_REST_Response | WP_Error * @since 0.1.0 * * @api {GET} /wp-json/buddyboss/v1/topics/dropdown/:id Topic Actions * @apiName DropdownBBPTopic * @apiGroup Forum Topics * @apiDescription Siblings of the topic. * @apiVersion 1.0.0 * @apiPermission LoggedInUser * @apiParam {Number} id A unique numeric ID for the topic. */ public function dropdown_items( $request ) { $topic_id = $request->get_param( 'id' ); $parent = bbp_get_topic_forum_id( $topic_id ); $page = $request->get_param( 'page' ); $per_page = $request->get_param( 'per_page' ); $topics_query = new WP_Query( array( 'post_type' => bbp_get_topic_post_type(), 'post_status' => 'publish', 'post__not_in' => array( $topic_id ), 'post_parent' => $parent, 'posts_per_page' => $per_page, 'paged' => $page, 'orderby' => 'menu_order title', 'order' => 'ASC', 'disable_categories' => true, ) ); $topics = $topics_query->posts; if ( empty( $topics ) ) { $retval = new WP_Error( 'bp_rest_no_other_topics', __( 'No discussions available', 'buddyboss' ), array( 'status' => 404, ) ); } foreach ( $topics as $topic ) { $data[] = array( 'id' => $topic->ID, 'title' => array( 'raw' => $topic->post_title, 'rendered' => bbp_get_topic_title( $topic->ID ), ), ); } $response = rest_ensure_response( $data ); $response = bp_rest_response_add_total_headers( $response, $topics_query->found_posts, $per_page ); /** * Fires after a list of topics is fetched via the REST API. * * @param array $topics Fetched Topics. * @param WP_REST_Response $response The response data. * @param WP_REST_Request $request The request sent to the API. * * @since 0.1.0 */ do_action( 'bp_rest_topics_dropdown_items', $topics, $response, $request ); return $response; } /** * Check if a given request has access to view the siblings of the topic. * * @param WP_REST_Request $request Full data about the request. * * @return bool|WP_Error * @since 0.1.0 */ public function dropdown_items_permissions_check( $request ) { $retval = true; if ( ! is_user_logged_in() ) { $retval = new WP_Error( 'bp_rest_authorization_required', __( 'Sorry, you need to be logged in to perform the action.', 'buddyboss' ), array( 'status' => rest_authorization_required_code(), ) ); } $topic = bbp_get_topic( $request['id'] ); if ( true === $retval && empty( $topic ) ) { $retval = new WP_Error( 'bp_rest_topic_invalid_id', __( 'Invalid topic ID.', 'buddyboss' ), array( 'status' => 404, ) ); } /** * Filter the topic `dropdown_items` permissions check. * * @param bool|WP_Error $retval Returned value. * @param WP_REST_Request $request The request sent to the API. * * @since 0.1.0 */ return apply_filters( 'bp_rest_topic_dropdown_items_permissions_check', $retval, $request ); } /** * Get the forums schema, conforming to JSON Schema. * * @return array * @since 0.1.0 */ public function get_dropdown_item_schema() { $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'topics_dropdown', 'type' => 'object', 'properties' => array( 'id' => array( 'description' => __( 'Unique identifier for the topic.', 'buddyboss' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'title' => array( 'description' => __( 'The title of the topic.', 'buddyboss' ), 'context' => array( 'view', 'edit' ), 'type' => 'object', 'properties' => array( 'raw' => array( 'description' => __( 'Content for the title of the topic, as it exists in the database.', 'buddyboss' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), ), 'rendered' => array( 'description' => __( 'The title of the topic, transformed for display.', 'buddyboss' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), ), ), ), ), ); /** * Filters the topic dropdown schema. * * @param string $schema The endpoint schema. */ return apply_filters( 'bp_rest_topic_dropdown_schema', $this->add_additional_fields_schema( $schema ) ); } /** * Update favourites for the topic. * * @param integer $topic_id Topic ID. * @param boolean $value Action value. * @param integer $user_id Current users ID. * * @return bool|WP_Error */ protected function rest_update_favorite( $topic_id, $value, $user_id ) { if ( ! bbp_is_favorites_active() ) { return new WP_Error( 'bp_rest_bbp_topic_action_disabled', __( 'Favorites are no longer active.', 'buddyboss' ), array( 'status' => 404, ) ); } // Bail if user cannot add favorites for this user. if ( ! current_user_can( 'edit_user', $user_id ) ) { return new WP_Error( 'bp_rest_authorization_required', __( 'You do not have permission to do this.', 'buddyboss' ), array( 'status' => 404, ) ); } $favorited = bbp_is_user_favorite( $user_id, $topic_id ); $status = true; if ( true === $favorited && empty( $value ) ) { $status = bbp_remove_user_favorite( $user_id, $topic_id ); } elseif ( false === $favorited && ! empty( $value ) ) { $status = bbp_add_user_favorite( $user_id, $topic_id ); } return $status; } /** * Update status for the topic. * * @param integer $topic_id Topic ID. * @param boolean $value Action value. * * @return bool|WP_Error */ protected function rest_update_close( $topic_id, $value ) { // What is the user doing here? if ( ! current_user_can( 'moderate', $topic_id ) ) { return new WP_Error( 'bp_rest_authorization_required', __( 'You do not have permission to do this.', 'buddyboss' ), array( 'status' => 404, ) ); } $is_open = bbp_is_topic_open( $topic_id ); $status = true; if ( true === $is_open && ! empty( $value ) ) { $status = bbp_close_topic( $topic_id ); } elseif ( false === $is_open && empty( $value ) ) { $status = bbp_open_topic( $topic_id ); } return $status; } /** * Update Subscription for the topic. * * @param integer $topic_id Topic ID. * @param boolean $value Action value. * @param integer $user_id Current users ID. * * @return bool|WP_Error */ protected function rest_update_subscribe( $topic_id, $value, $user_id ) { if ( ! bbp_is_subscriptions_active() ) { return new WP_Error( 'bp_rest_bbp_topic_action_disabled', __( 'Subscriptions are no longer active.', 'buddyboss' ), array( 'status' => 404, ) ); } // Bail if user cannot add subscription for this user. if ( ! current_user_can( 'edit_user', $user_id ) ) { return new WP_Error( 'bp_rest_authorization_required', __( 'You do not have permission to do this.', 'buddyboss' ), array( 'status' => 404, ) ); } $status = true; $subscribed = bbp_is_user_subscribed( $user_id, $topic_id ); // Subscribed and unsubscribing. if ( true === $subscribed && empty( $value ) ) { $status = bbp_remove_user_subscription( $user_id, $topic_id ); // Not subscribed and subscribing. } elseif ( false === $subscribed && ! empty( $value ) ) { $status = bbp_add_user_subscription( $user_id, $topic_id ); } return $status; } /** * Update sticky things for the topic. * * @param integer $topic_id Topic ID. * @param string $action Action name to update. * @param boolean $value Action value. * * @return bool|WP_Error */ protected function rest_update_sticky( $topic_id, $action, $value ) { // What is the user doing here? if ( ! current_user_can( 'moderate', $topic_id ) ) { return new WP_Error( 'bp_rest_authorization_required', __( 'You do not have permission to do this.', 'buddyboss' ), array( 'status' => 404, ) ); } $is_super = ( 'super_sticky' === $action ) ? true : false; $is_sticky = bbp_is_topic_sticky( $topic_id ); $status = true; if ( true === $is_sticky && empty( $value ) ) { $status = bbp_unstick_topic( $topic_id ); } elseif ( false === $is_sticky && ! empty( $value ) ) { $status = bbp_stick_topic( $topic_id, $is_super ); } return $status; } /** * Make topics as spam or not. * * @param integer $topic_id Topic ID. * @param boolean $value Action value. * * @return bool|WP_Error */ protected function rest_update_spam( $topic_id, $value ) { // What is the user doing here? if ( ! current_user_can( 'moderate', $topic_id ) ) { return new WP_Error( 'bp_rest_authorization_required', __( 'You do not have permission to do this.', 'buddyboss' ), array( 'status' => 404, ) ); } $is_spam = bbp_is_topic_spam( $topic_id ); $status = true; if ( true === $is_spam && empty( $value ) ) { $status = bbp_unspam_topic( $topic_id ); } elseif ( false === $is_spam && ! empty( $value ) ) { $status = bbp_spam_topic( $topic_id ); } return $status; } /** * Move topic into trash or untrash. * * @param integer $topic_id Topic ID. * @param boolean $value Action value. * * @return bool|WP_Error */ protected function rest_update_trash( $topic_id, $value ) { // What is the user doing here? if ( ! current_user_can( 'moderate', $topic_id ) ) { return new WP_Error( 'bp_rest_authorization_required', __( 'You do not have permission to do this.', 'buddyboss' ), array( 'status' => 404, ) ); } $post_status = get_post_status( $topic_id ); if ( 'trash' === $post_status && empty( $value ) ) { $status = wp_untrash_post( $topic_id ); } elseif ( 'trash' !== $post_status && ! empty( $value ) ) { $status = wp_trash_post( $topic_id ); } return ( ! empty( $status ) && ! is_wp_error( $status ) ? true : $status ); } }
Changelog
Version | Description |
---|---|
0.1.0 | Introduced. |
Methods
- __construct — Constructor.
- action_items — Actions on Topic
- action_items_permissions_check — Check if a given request has access to perform an action on topic.
- dropdown_items — Topic's Dropdown
- dropdown_items_permissions_check — Check if a given request has access to view the siblings of the topic.
- get_dropdown_item_schema — Get the forums schema, conforming to JSON Schema.
- merge_item — Merge Topic
- merge_item_permissions_check — Check if a given request has access to merge a topic.
- register_routes — Register the component routes.
- rest_update_close — Update status for the topic.
- rest_update_favorite — Update favourites for the topic.
- rest_update_spam — Make topics as spam or not.
- rest_update_sticky — Update sticky things for the topic.
- rest_update_subscribe — Update Subscription for the topic.
- rest_update_trash — Move topic into trash or untrash.
- split_item — Split Topic
- split_item_permissions_check — Check if a given request has access to merge a topic.
Questions?
We're always happy to help with code or other questions you might have! Search our developer docs, contact support, or connect with our sales team.