Wordpress - 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 :)


My idea is something simple.

  • You can make an Edit Suggestion link at bottom of posts that has a custom defined template, in that use a textbox (maybe with an editor) that's linked to a custom taxonomy with the default value of post content.

  • Any changes to content will be compared to original post content after submitting (as Draft) and Entering CAPTCHA code with Diff algorithms like PHP inline-diff package or Text-Diff PEAR Package or alternatively using a PHP function according to this for not too-long texts with combination of CSS.

  • Then by saving values in 3 custom Meta Boxes (in that taxonomy back-end add/edit page) that show

    1. Original Content
    2. Edited Version
    3. User nickname and His Email

    and saving Post ID maybe with a update_option() function for later use.

  • After reading edited version and acceptance by admin, that post will be replaced the original one as you coded in functions.php.


Well this is rather complicated, a proper answer would take considerable time to write. So this isn't a real answer just some thoughts..

Using WordPress build in wp_update_post via ajax would give you the needed revision history but not the capability needed to approve edits.

Creating drafts from edits is not possible by default but has been discussed here, Is there any way to draft a revision of a published page or post? What workarounds have you used?

You can try and use Front-end Editor but you will have no control over edits being published, so try and mash it with with another plugin like Revisionary which does allow for permissions based edits, I have no idea if they will work together.

If they don't you will have to hack a plugin based on the 2 above plugins or write something from scratch.

My scratch approach would be to have a button that goes to another page that outputs the post content/data using JSON, which is easier to work with when using Ajax and WYSIWYG editors. The save button would post as a draft instead of publish and that way you would have control over the edits (see above WPSE discussion on how to accomplish this, it's rather daunting).

There are additional complications when doing this such as sanitization, encoding, spam, media handling, custom fields, timestamps, memory, etc. The good news is that wordpress already has a revision system you can plug into and a decent ability to handle multiple editors.

ps. This is a good idea for a plugin.