web-dev-qa-db-fra.com

Comment valider la post-création XML-RPC et annuler si nécessaire?

J'ai une recette IFTTT qui crée des publications pour moi en certaines occasions, mais pour une raison étrange, elle crée trois, parfois quatre publications du même contenu.

J'aimerais ajouter un hook/callback add_action pour valider ce qui sera un nouveau message et, s'il existe déjà, annuler le message ou le déplacer vers la corbeille ou quelque chose du genre.

J'ai trouvé le xmlrpc_prepare_post mais je ne pense pas pouvoir l'annuler à partir de là. À moins que je puisse mettre à jour certains attributs et les mettre à la corbeille?

Mise à jour.

J'ai essayé ce qui suit et cela n'entre que dans xmlrpc_call, mais jamais dans xmlrpc_wp_insert_post_meta. J'ai même ajouté un appel add_filter codé en dur (pas seulement en cas de si newPost) et mes journaux ne montrent jamais un tel message de journalisation.

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

Dans les journaux, j'ai ce genre d'instructions de journal:

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 

Ensuite, je vois les autres filtres que j'ai ajoutés lors de la création d'un article. Je sais que je finirai probablement par corriger les articles, mais je suis sûr que ces filtres/actions XMLRPC devraient fonctionner.

D'après les journaux, je le vois aller dans if newPost et ajouter le filtre 'xmlrpc_wp_insert_post_data' mais il n'exécute jamais la fonction hueman_xmlrpc_wp_insert_post_data ... :((

7
Vallieres

Il semble que le filtre xmlrpc_prepare_post ne soit appliqué qu'à la sortie des méthodes wp_getPost et wp_getRevision de la classe wp_xmlrpc_server.

Ce serait génial si cette ligne de code:

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

serait remplacé par des arguments d'entrée supplémentaires, par exemple:

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

mais cela ne se produira pas selon ce ticket .

Nous devons donc trouver un autre moyen de contourner ce problème.

Solutions possibles:

Voici quelques idées non testées utilisant les filtres xmlrpc_call et xmlrpc_wp_insert_post_data.

Modifie les données d'entrée avant qu'elles soient insérées avec 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;  
}

Ici, nous essayons de trouver une publication existante avec le même titre, lors des appels wp.newPost. Si nous en trouvons un, nous ajoutons que c'est ID au tableau $post_data, il sera donc mis à jour.

Notez que nous aurions aussi pu modifier le post_status avec:

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

toutes les insertions supplémentaires sont donc dirigées vers la corbeille.

Vous pouvez également essayer de créer votre propre méthodeinsert via le filtre xmlrpc_methods.

J'espère que vous pourrez adapter cela à vos besoins, en supposant que cela fonctionne ;-)

Update : J'ai maintenant testé cette idée et ça marche, je peux à la fois supprimer les posts dupliqués ou le mettre à jour directement.

Merci à @DavidPeterson pour avoir remarqué mes erreurs de syntaxe idiotes de PHP depuis la modification du code dans l'éditeur WPSE ;-)

7
birgire

Dans le fichier wp-includes/class-wp-xmlrpc-server.php

Dans la fonction mw_newPost () après ces lignes:

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

Ajouter:

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

Et créez une déclaration:

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
Brynner Ferreira