# bbp-core/2.5.1/includes/features/frmx-inline-edit.php

Forumax – AI Powered Advanced Community Forum Plugin, version 2.5.1. 296 lines.

- Page: https://pluginprobe.com/plugins/bbp-core/2.5.1/code/includes/features/frmx-inline-edit.php
- Raw: https://pluginprobe.com/plugins/bbp-core/2.5.1/raw/includes/features/frmx-inline-edit.php
- Modified: 2026-10-12T12:43:18+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/bbp-core/2.5.1/code/includes/features/frmx-inline-edit.php#L10-L20`.

```php
<?php
/**
 * Forumax Inline Edit Feature
 *
 * Provides AJAX-based inline editing for topics and replies
 * so users can edit content without leaving the page.
 *
 * @package Forumax
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class Forumax_Inline_Edit
 *
 * Handles inline editing for bbPress topics and replies.
 */
class Forumax_Inline_Edit {

	/**
	 * Constructor — register AJAX actions.
	 */
	public function __construct() {
		// Topic inline edit actions.
		add_action( 'wp_ajax_forumax_get_topic_content', array( $this, 'get_topic_content' ) );
		add_action( 'wp_ajax_forumax_save_topic_edit', array( $this, 'save_topic_edit' ) );

		// Reply inline edit actions.
		add_action( 'wp_ajax_forumax_get_reply_content', array( $this, 'get_reply_content' ) );
		add_action( 'wp_ajax_forumax_save_reply_edit', array( $this, 'save_reply_edit' ) );
	}

	/**
	 * Revision created by the current wp_update_post() call.
	 *
	 * @var int
	 */
	private $revision_id = 0;

	/**
	 * Start recording the revision wp_update_post() creates.
	 *
	 * @return void
	 */
	private function watch_revisions() {
		$this->revision_id = 0;
		add_action( '_wp_put_post_revision', array( $this, 'record_revision' ) );
	}

	/**
	 * Stop recording and return the recorded revision ID.
	 *
	 * @return int
	 */
	private function stop_watching_revisions() {
		remove_action( '_wp_put_post_revision', array( $this, 'record_revision' ) );
		return (int) $this->revision_id;
	}

	/**
	 * Remember a freshly stored revision.
	 *
	 * @param int $revision_id Revision ID.
	 * @return void
	 */
	public function record_revision( $revision_id ) {
		$this->revision_id = (int) $revision_id;
	}

	/**
	 * AJAX handler: Get raw topic content for editing.
	 *
	 * Returns the topic title and raw content for the inline editor.
	 */
	public function get_topic_content() {
		check_ajax_referer( 'forumax-nonce', 'nonce' );

		$topic_id = isset( $_POST['topic_id'] ) ? absint( $_POST['topic_id'] ) : 0;

		if ( ! $topic_id ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid topic ID.', 'forumax' ) ) );
		}

		// Verify the user can edit this topic.
		if ( ! current_user_can( 'edit_post', $topic_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to edit this topic.', 'forumax' ) ) );
		}

		$topic = get_post( $topic_id );

		if ( ! $topic || bbp_get_topic_post_type() !== $topic->post_type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Topic not found.', 'forumax' ) ) );
		}

		wp_send_json_success( array(
			'title'   => $topic->post_title,
			'content' => $topic->post_content,
		) );
	}

	/**
	 * AJAX handler: Save inline-edited topic.
	 *
	 * Updates the topic title and content via AJAX.
	 */
	public function save_topic_edit() {
		check_ajax_referer( 'forumax-nonce', 'nonce' );

		$topic_id = isset( $_POST['topic_id'] ) ? absint( $_POST['topic_id'] ) : 0;

		if ( ! $topic_id ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid topic ID.', 'forumax' ) ) );
		}

		// Verify the user can edit this topic.
		if ( ! current_user_can( 'edit_post', $topic_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to edit this topic.', 'forumax' ) ) );
		}

		$topic = get_post( $topic_id );

		if ( ! $topic || bbp_get_topic_post_type() !== $topic->post_type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Topic not found.', 'forumax' ) ) );
		}

		// Sanitize inputs.
		$new_title   = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';
		$new_content = isset( $_POST['content'] ) ? wp_kses_post( wp_unslash( $_POST['content'] ) ) : '';

		if ( empty( $new_title ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Title cannot be empty.', 'forumax' ) ) );
		}

		if ( empty( $new_content ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Content cannot be empty.', 'forumax' ) ) );
		}

		// Update the topic. wp_update_post() expects slashed data; passing
		// unslashed values stripped every backslash from the content.
		$this->watch_revisions();
		$updated = wp_update_post( wp_slash( array(
			'ID'           => $topic_id,
			'post_title'   => $new_title,
			'post_content' => $new_content,
		) ), true );

		if ( is_wp_error( $updated ) ) {
			wp_send_json_error( array( 'message' => $updated->get_error_message() ) );
		}

		// Log the revision (bbPress tracks edits). wp_update_post() already
		// stored it, so a second wp_save_post_revision() call returns nothing.
		$revision_id = $this->stop_watching_revisions() ?: wp_save_post_revision( $topic_id );
		if ( $revision_id ) {
			bbp_update_topic_revision_log( array(
				'topic_id'    => $topic_id,
				'revision_id' => $revision_id,
				'author_id'   => bbp_get_current_user_id(),
				'reason'      => esc_html__( 'Inline edit', 'forumax' ),
			) );
		}

		// Return the rendered content for display.
		$updated_topic = get_post( $topic_id );

		wp_send_json_success( array(
			'title'            => esc_html( $updated_topic->post_title ),
			'content'          => apply_filters( 'bbp_get_topic_content', $updated_topic->post_content, $topic_id ),
			'message'          => esc_html__( 'Topic updated successfully.', 'forumax' ),
		) );
	}

	/**
	 * AJAX handler: Get raw reply content for editing.
	 *
	 * Returns the reply raw content for the inline editor.
	 */
	public function get_reply_content() {
		check_ajax_referer( 'forumax-nonce', 'nonce' );

		$reply_id = isset( $_POST['reply_id'] ) ? absint( $_POST['reply_id'] ) : 0;

		if ( ! $reply_id ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid reply ID.', 'forumax' ) ) );
		}

		// Verify the user can edit this reply.
		if ( ! current_user_can( 'edit_post', $reply_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to edit this reply.', 'forumax' ) ) );
		}

		$reply = get_post( $reply_id );

		if ( ! $reply || bbp_get_reply_post_type() !== $reply->post_type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Reply not found.', 'forumax' ) ) );
		}

		wp_send_json_success( array(
			'content' => $reply->post_content,
		) );
	}

	/**
	 * AJAX handler: Save inline-edited reply.
	 *
	 * Updates the reply content via AJAX.
	 */
	public function save_reply_edit() {
		check_ajax_referer( 'forumax-nonce', 'nonce' );

		$reply_id = isset( $_POST['reply_id'] ) ? absint( $_POST['reply_id'] ) : 0;

		if ( ! $reply_id ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid reply ID.', 'forumax' ) ) );
		}

		// Verify the user can edit this reply.
		if ( ! current_user_can( 'edit_post', $reply_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to edit this reply.', 'forumax' ) ) );
		}

		$reply = get_post( $reply_id );

		if ( ! $reply || bbp_get_reply_post_type() !== $reply->post_type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Reply not found.', 'forumax' ) ) );
		}

		// Sanitize input.
		$new_content = isset( $_POST['content'] ) ? wp_kses_post( wp_unslash( $_POST['content'] ) ) : '';

		if ( empty( $new_content ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Content cannot be empty.', 'forumax' ) ) );
		}

		// Update the reply (slashed, see save_topic_edit()).
		$this->watch_revisions();
		$updated = wp_update_post( wp_slash( array(
			'ID'           => $reply_id,
			'post_content' => $new_content,
		) ), true );

		if ( is_wp_error( $updated ) ) {
			wp_send_json_error( array( 'message' => $updated->get_error_message() ) );
		}

		// Log the revision (bbPress tracks edits).
		$revision_id = $this->stop_watching_revisions() ?: wp_save_post_revision( $reply_id );
		if ( $revision_id ) {
			bbp_update_reply_revision_log( array(
				'reply_id'    => $reply_id,
				'revision_id' => $revision_id,
				'author_id'   => bbp_get_current_user_id(),
				'reason'      => esc_html__( 'Inline edit', 'forumax' ),
			) );
		}

		// Return the rendered content for display.
		$updated_reply = get_post( $reply_id );

		// Set up global post data so action hooks can access the correct reply.
		global $post;
		$original_post = $post;
		$post = $updated_reply;
		setup_postdata( $post );

		// Capture the full rendered content including action hooks.
		ob_start();

		// Trigger before content action (includes "Replying to" label).
		do_action( 'bbp_theme_before_reply_content' );

		// Output the reply content using bbPress function.
		bbp_reply_content( $reply_id );

		// Trigger after content action (includes nested reply button).
		do_action( 'bbp_theme_after_reply_content' );

		$rendered_content = ob_get_clean();

		// Restore original post data.
		$post = $original_post;
		if ( $original_post ) {
			setup_postdata( $original_post );
		}
		wp_reset_postdata();

		wp_send_json_success( array(
			'content' => $rendered_content,
			'message' => esc_html__( 'Reply updated successfully.', 'forumax' ),
		) );
	}
}

// Initialize the inline edit feature.
new Forumax_Inline_Edit();

```
