How to enable suggested edits?

Diff the post content, title and author

As had to do something related some month ago, here’s the easiest and most future proof way (that I could fine) to check if there’s a change made to the content or title or if the author changed:

// Update Title
'' !== wp_text_diff(
    $el['post_title'],
    $GLOBALS['post']->post_title
)
    AND $GLOBALS['post']->post_title = $el['post_title'];
// Update Content
'' !== wp_text_diff(
    $el['post_content'],
    $GLOBALS['post']->post_content
)
    AND $GLOBALS['post']->post_content = $el['post_content'];
// Update author
$GLOBALS['post']->post_author !== $el['post_author']
    AND $GLOBALS['post']->post_author = $el['post_author'];

To explain my scenario briefly: I was fetching posts from a remote location via a remote API. Then I returned the global $post, during a single post loop, containing either the original data or the new data. This way I moved around setting all the other post values that I didn’t need to check for changes.

Proposing the edit

The main fact one has to keep in mind when searching a place where a copy-edit of the post content could be (temporarily) saved is that the content is a db entry of longtext. So the place where one wants to save the suggested edit should meet that requirement. Comments do that.

Then there’s the nice fact that they offer an API to place them nicely in a loop, so it integrates smoothly, is highly customizable and can quickly be setup. Last but not least most themes already come with comments integrated so it’s easy to piggyback on the system and hook into nearly any available theme.

I’d suggest to just (either) extend or alter the comment form. Use either the following or add additional fields with a callback hooked to comment_form_default_fields.

<?php
// Add it for logged in users and guests:
add_action( 'comment_form_logged_in_after', 'wpse_proposed_edit_textarea' );
add_action( 'comment_form_after_fields', 'wpse_proposed_edit_textarea' );
function wpse_proposed_edit_textarea()
{
    ?>
    <p class="comment-form-title">
        <label for="wpse_propsed_edit">
            <?php _e( 'Propose Edit', 'your_textdomain' ); ?>
        </label>
        <textarea name="wpse_propsed_edit" id="wpse_propsed_edit">
            <?php the_content(); ?>
        </textarea>
    </p>
    <input type="hidden" name="comment_approved" id="comment_approved" value="0" />
    <?php
}

So I’ve added a hidden field for comment_approved with an value of 0 to set it in the queue. Not sure if this will work or if this (core) value is actually comment meta data and needs to get added by using add_comment_meta() during saving. If not, you could use something along the following lines of code

add_filter( 'pre_comment_approved' , 'wpse_pre_suggest_edit', 100, 2 );
function wpse_pre_suggest_edit( $approved , $commentdata )
{
    // You might need to inspect $commentdata 
    // to determine approval, disapproval, or spam status
    if ( ! empty( $commentdata['wpse_propsed_edit'] ) )
    {
        # Now add a filter to the comment post action, so we save a meta entry
        add_action( 'comment_post', 'wpse_set_proposed_edit' );
        return 0;
    }

    return 1;
}

// This function makes it easier for us to identify the comments by their meta value
function wpse_set_proposed_edit( $comment_id );
{
    // Only run once
    remove_filter( current_filter(), __FUNCTION__ );

    add_comment_meta( $comment_id, 'proposed_edit', true, true );
}

Displaying the comments on the admin side

Here I’d go with a simple class extension and a custom admin page:

function wpse_add_proposed_edits_admin_page()
{
    add_menu_page(
        'Proposed Edits',
        'Suggested Edits',
        'activate_plugins',
        'proposed_edits',
        'wpse_proposed_edits_page_cb'
    );
}
add_action( 'admin_menu', 'wpse_add_proposed_edits_admin_page' );

function wpse_proposed_edits_page_cb()
{
    $proposed_edits_table = new WP_Proposed_Edits_Table();
    $proposed_edits_table->prepare_items(); 
    $proposed_edits_table->display(); 
}

class WP_Proposed_Edits_Table extends WP_List_Table
{
    // Override List table default logic in here
}

More info can be found on WPEngineer.

Approving edits

You could then add custom actions and process the proposed edits using the first code I showed to check if there was a change and then simply update the post. The comment itself holds a value with a key of comment_post_ID, so identifying the edited posts ID is straight forward.

Final note

I’d like to see the final plugin as well. Please link it here 🙂

Leave a Comment