7

I have an IFTTT recipe that creates posts for me on some occasion, but for some weird reason it creates three, sometimes four posts of the same content.

I would like to add an add_action hook/callback to validate what will be a new post and, if it already exists, cancel the post, or move it to trash or something like it.

I found the the xmlrpc_prepare_post but I don't think I can cancel it from there. Unless I can update some attribute and set it to trash?

Update.

I tried the following and it only ever gets into the xmlrpc_call, but never ever inside xmlrpc_wp_insert_post_meta. I even added a hard-coded add_filter call (not just in case of if newPost) and my logs never show such logging message.

Here's the code:

function hueman_xmlrpc_call( $method )
{
    error_log("XMLRPC | hueman_xmlrpc_call Method = $method \n" , 3, '/home/.../debug.log');
    if( 'wp.newPost' === $method || 'metaWeblog.newPost' === $method )
    {
        error_log("XMLRPC | hueman_xmlrpc_call  method = " . $method . " \n" , 3, '/home/.../debug.log');
        add_filter( 'xmlrpc_wp_insert_post_data', 'hueman_xmlrpc_wp_insert_post_data' );
    }
}
add_action('xmlrpc_call', 'hueman_xmlrpc_call', 1 );


add_filter( 'xmlrpc_wp_insert_post_data', 'hueman_xmlrpc_wp_insert_post_data' );

function hueman_xmlrpc_wp_insert_post_data( $post_data )
{
    error_log("XMLRPC | hueman_xmlrpc_wp_insert_post_data  \n" , 3, '/home/.../debug.log');
    // Check if the post title exists:
    $tmp = get_page_by_title( 
        $post_data['post_title'], 
        OBJECT, 
        $post_data['post_type'] 
    );

    if( is_object ( $tmp ) )
    {
        // Go from 'insert' to 'update' mode within wp_insert_post():
        //$post_data['ID'] = $tmp->ID; 

        $post_data['post_status'] = 'trash';
        error_log("XMLRPC | hueman_xmlrpc_wp_insert_post_data I TRASHED IT! \n" , 3, '/home/.../debug.log');
    }

    return $post_data;  
}

In the logs, I have this kind of log statements:

XMLRPC | hueman_xmlrpc_call Method = mt.supportedMethods 
XMLRPC | hueman_xmlrpc_call Method = metaWeblog.getRecentPosts 
XMLRPC | hueman_xmlrpc_call Method = mt.supportedMethods 
XMLRPC | hueman_xmlrpc_call Method = metaWeblog.getRecentPosts 
XMLRPC | hueman_xmlrpc_call Method = mt.supportedMethods 
XMLRPC | hueman_xmlrpc_call Method = metaWeblog.getRecentPosts 
XMLRPC | hueman_xmlrpc_call Method = metaWeblog.getCategories 
XMLRPC | hueman_xmlrpc_call Method = metaWeblog.newPost 
XMLRPC | hueman_xmlrpc_call  method = metaWeblog.newPost 

Then, I see other filters I added when an article is created. I know I will probably end-up fixing the articles there but I'm sure this XMLRPC filters/actions should work.

From the logs, I see it go inside the if newPost and adding the filter 'xmlrpc_wp_insert_post_data' but it never executes the hueman_xmlrpc_wp_insert_post_data function... :(

  • 4
    A very good (and interesting) question. Might you please file an edit and explain how IFTTT works together with WP, how you set it up and how you point to the XML-RPLC interface? Please be as verbose as possible as this has the potential to become a very epic question. Thanks. – kaiser Aug 9 '14 at 8:04
  • It's actually very simple. I used IFTTT with the RSS 2 Wordpress recipe. Plugged in my author RSS feed from the external site. In the Wordpress I logged in user my regular Wordpress user. here's the channel: ifttt.com/wordpress and the recipe: ifttt.com/recipes/19382-rss-feed-to-wordpress-blog – Vallieres Nov 4 '14 at 19:23
7

It looks like the xmlrpc_prepare_post filter is only applied to the output of the wp_getPost and wp_getRevision methods of the wp_xmlrpc_server class.

It would be great if this code line:

do_action( 'xmlrpc_call', 'wp.newPost' );

would be replaced with extra input arguments, for example:

do_action( 'xmlrpc_call', 'wp.newPost', ..., $content_struct );

but that's not going to happen according to this ticket.

So we need to find another way around this.

Possible workarounds:

Here are some untested ideas using the xmlrpc_call and the xmlrpc_wp_insert_post_data filters.

Modify input data before it's inserted with wp_insert_posts():

/**
 * Prevent duplicate posts when doing wp.newPost via XML-RPC
 *
 * @see http://wordpress.stackexchange.com/a/157261/26350
 */

add_action( 'xmlrpc_call', 'wpse_xmlrpc_call' );

function wpse_xmlrpc_call( $method )
{
    if( 'wp.newPost' === $method )
        add_filter( 'xmlrpc_wp_insert_post_data', 'wpse_xmlrpc_wp_insert_post_data' );
}

function wpse_xmlrpc_wp_insert_post_data( $post_data )
{
    // Check if the post title exists:
    $tmp = get_page_by_title( 
        $post_data['post_title'], 
        OBJECT, 
        $post_data['post_type'] 
    );

    // Go from 'insert' to 'update' mode within wp_insert_post():
    if( is_object ( $tmp ) )
        $post_data['ID'] = $tmp->ID; 

    return $post_data;  
}

Here we try to find an existing post with the same title, during wp.newPost calls. If we find one, we add it's ID to the $post_data array, so it will be updated instead.

Notice that we could also have modified the post_status instead with:

    $post_data['post_status'] = 'trash'; 

so all extra inserts are directed to the trash.

You could also try to create your own insert method via the xmlrpc_methods filter.

I hope you can modify this to your needs, assuming this will work ;-)

Update: I've now tested this idea and it works, I can both trash the duplicated posts or update it directly.

Thanks to @DavidPeterson for noticing my silly PHP syntax errors from when I edited the code within the WPSE editor ;-)

  • This is exactly what I was looking for! I implemented your solution, hopefully it will work properly and place all duplicate in the trash. I'll know next time the XMLRPC gets triggered! – Vallieres Aug 14 '14 at 20:33
  • Hello, it did not work as intended. See below what I did. :( – Vallieres Sep 21 '14 at 14:59
  • Hi @vallieres, thanks for reporting back. Hopefully I can find the problem. – birgire Sep 22 '14 at 8:56
  • Thanks @birgire, it really seems to be area where documentation and/or examples are not to be found. You might think I'm not the only one that wants to filter XMLRPC articles... – Vallieres Sep 22 '14 at 13:46
  • were you able to make it work? On my end, it does not seem to work at all :( – Vallieres Oct 15 '14 at 1:05
1

In the wp-includes/class-wp-xmlrpc-server.php file

Inside the function mw_newPost() after these lines:

$post_title = isset( $content_struct['title'] ) ? $content_struct['title'] : null;
$post_content = isset( $content_struct['description'] ) ? $content_struct['description'] : null;

Add:

global $wpdb;
$some_post = $wpdb->get_row("
    SELECT ID
    FROM {$wpdb->posts}
    WHERE post_title = '{$post_title}'
");

And create a statement:

if (!empty($some_post->ID) and $some_post->ID > 0) {
    return 0;
} else {
    // the rest of the code that already exists in the function
    /*
    $post_status = $publish ? 'publish' : 'draft';
    ...
    return strval($post_ID);
    */
}
  • 1
    Hi, ingenious solution but that would be easily overriden by any Wordpress update following the change. Any way to make it work from a plugin or functions.php ? – Vallieres Aug 9 '15 at 21:11
  • 1
    @Vallieres, Yes, you're right, then I've disabled WordPress updates. I wanna create a plugin soon. – Brynner Ferreira Aug 10 '15 at 3:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.