BP_REST_Topics_Actions_Endpoint::split_item( WP_REST_Request $request )

Split Topic

Description

Parameters

$request

(WP_REST_Request) (Required) Full details about the request.

Return

(WP_REST_Response) | WP_Error

Source

File: bp-forums/classes/class-bp-rest-topics-actions-endpoint.php

	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',
			)
		);
	}

Changelog

Changelog
Version Description
0.1.0 Introduced.

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.