web-dev-qa-db-ja.com

XML-RPC投稿作成を検証し、必要に応じてキャンセルする方法

私は IFTTTレシピ を持っていることがありますが、奇妙な理由でそれは同じ内容の記事を3つ、場合によっては4つ作成します。

私はadd_actionフック/コールバックを追加して新しい投稿になるものを検証し、それが既に存在する場合は投稿をキャンセルするか、ゴミ箱などに移動します。

私はxmlrpc_prepare_postを見つけましたが、そこからキャンセルすることはできないと思います。ある属性を更新してそれをゴミ箱に設定できないのであれば?

Update.

私は以下を試しました、そして、それは今までxmlrpc_callに入るだけです、しかし決してxmlrpc_wp_insert_post_metaの中に決して入ったことがありません。私はハードコードされたadd_filter呼び出しさえ追加しました(if newPostの場合だけではありません)、そして私のログはそのようなロギングメッセージを決して表示しません。

これがコードです:

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;  
}

ログには、このようなログステートメントがあります。

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 

その後、記事が作成されたときに追加した他のフィルタが表示されます。私はたぶんそこで記事を修正することになるでしょうが、私はこのXMLRPCフィルタ/アクションがうまくいくはずであると確信しています。

ログから、私はそれがif newPostの中に入ってフィルタ 'xmlrpc_wp_insert_post_data'を追加するのを見ますが、それはhueman_xmlrpc_wp_insert_post_data関数を決して実行しません... :(

7
Vallieres

xmlrpc_prepare_postフィルタはwp_getPostクラスのwp_getRevisionおよびwp_xmlrpc_serverメソッドの出力にのみ適用されるようです。

このコード行があればそれは素晴らしいでしょう:

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

以下のように、追加の入力引数に置き換えられます。

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

しかし、これは ticket に従っては起こらないでしょう。

だから我々はこれを回避する別の方法を見つける必要があります。

考えられる回避策:

これはxmlrpc_callxmlrpc_wp_insert_post_dataフィルターを使った未検証のアイデアです。

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;  
}

ここでは、wp.newPost呼び出し中に、同じタイトルの既存の投稿を見つけようとします。見つかった場合は、それをID$post_data配列に追加するので、代わりに更新されます。

代わりにpost_statusを変更することもできます。

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

そのため、追加の挿入はすべて trash に送られます。

xmlrpc_methodsフィルタを介して 独自に作成 insert methodを試すこともできます。

これがうまくいくと仮定して、あなたのニーズに合わせてこれを変更できることを願っています;-)

Update:私は今このアイディアをテストしました、そしてそれはうまくいきます、私は両方とも重複したポストをゴミ箱に入れるか、それを直接更新することができます。

WPSEエディタでコードを編集したときの愚かなPHP構文エラーに気付いた@DavidPetersonに感謝します;-)

7
birgire

Wp-includes/class-wp-xmlrpc-server.phpファイル内

これらの行の後の関数mw_newPost()の中:

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

追加:

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

そしてステートメントを作成します。

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