Vérifier la mise à jour par rapport au nouveau message sur l'action save_post


21

Est-il possible dans l'action save_post de déterminer s'il s'agit d'une nouvelle publication en cours de création ou d'une publication existante en cours de mise à jour?


Je ne pense pas que ce soit possible. Voir mon commentaire ci-dessous la réponse de @ moralida. Pourquoi avez-vous besoin de savoir s'il s'agit d'une nouvelle publication ou d'une mise à jour? Il peut y avoir une solution de rechange ou une approche alternative.
Stephen Harris

Réponses:


16

Depuis la version 3.7 de WordPress. - IIRC - le save_postcrochet - plus d'informations sur le crochet et son utilisation dans Code Reference:save_post et Codex:save_post - a un troisième paramètre $updatequi peut être utilisé pour déterminer exactement cela.

@param int $ post_ID ID de publication.
@param WP_Post $ post Objet Post.
@param bool $ update Qu'il s'agisse d'une publication existante en cours de mise à jour ou non.


Remarque:

$updaten'est pas toujours true- vous pouvez le voir et le tester vous-même avec le code ci-dessous. Cependant, il n'est pas bien documenté, peut-être loin d'être nommé de manière optimale, et crée donc des attentes trompeuses. Le code ci-dessous peut être utilisé pour certains débogages, essayez de savoir quand intercepter l'exécution du code, sinon vous ne verrez pas les informations / messages. Je pense que le coupable d'un comportement trompeur est la gestion des révisions et des sauvegardes automatiques - qui pourraient être désactivées, mais je ne le recommande pas et je ne l'ai pas testé. Je ne sais pas si cela justifie un ticket Trac , donc je n'en ai pas ouvert un, si vous le pensez, veuillez suivre le lien et le faire vous-même. En dehors de cela, comme indiqué dans les commentaires, si vous avez un problème spécifique, posez une nouvelle question.

add_action( 'save_post', 'debug_save_post_update', 10, 3 );
function debug_save_post_update( $ID, $post, $update ) {

  echo '<pre>';
  print_r( $post ); echo '<br>';
  echo '$update == ';
  echo $update ? 'true' : 'false';

  //conditions
  if( ! $update && $post->post_status == "auto-draft" ) {
    // applies to new post
    echo ' && $post->post_status == "auto-draft"';
    //die();
  } else if ( ! $update ) {
    // applies basically to the (auto saved) revision 
    //die();
  } else {
    // applies to updating a published post
    // when there is a revision, which is normally the case, 
    // standard behavior of WordPress, then it is considered 
    // an update, which is where the confusion sets in
    // there are other methods, like checking time or post status
    // depending on your use case it might be more appropriate 
    // to use one of those alternatives 
    //die();
  }

  echo '</pre>';
  //die();
}

3
Le $updateparamètre est TOUJOURS vrai même s'il s'agit d'un nouveau message. Ce paramètre est donc inutile. Je ne sais pas si cela a déjà fonctionné, mais c'est sûr que l'enfer ne fonctionne pas comme il est documenté dans la dernière version de wordpress 4.8.
Solomon Closson

@SolomonClosson Si vous regardez wp_publish_post, alors oui. Mais ce n'est pas vrai pour son utilisation dans wp_insert_post. J'ai écrit une fonction de débogage, je l'ajoute à la réponse.
Nicolai

@SolomonClosson Si vous avez un problème concret réel, veuillez poser une nouvelle question. Jetez un oeil aux révisions de la fonction de débogage une explication.
Nicolai

Le save_posthook a un 3ème paramètre qui est toujours défini sur TRUE, donc vous ne savez pas ce que cela a à voir avec les autres hooks, sans parler des autres hooks. Je parle du crochet dans votre réponse. Ceci est une erreur.
Solomon Closson

@SolomonClosson Comme je l'ai dit, le crochet se produit deux fois: wp_insert_post(), wp_publish_post(). Ce dernier n'est que de futurs postes, il $updatedevrait y en avoir toujours true. Sinon, en ce qui concerne wp_insert_post(), $updaten'est pas toujours true.
Nicolai

11

La façon dont j'effectue cette vérification (dans une fonction accrochée) consiste à comparer la date de publication et la date de modification (en GMT pour la normalisation)

function check_new_vs_update( $post_id ){
    $myPost        = get_post($post_id);
    $post_created  = new DateTime( $myPost->post_date_gmt );
    $post_modified = new DateTime( $myPost->post_modified_gmt );

    if( abs( $post_created->diff( $post_modified )->s ) <= 1 ){
        // New post
    }else{
        // Updated post
    }
}
add_action('save_post', 'check_new_vs_update' );

Cela fonctionne parce que même à la création, le post a une date «modifiée» qui lui est attachée, ce qui est exactement la même que la date «créée», mais nous autorisons un écart de 1 seconde dans les deux cas au cas où une seconde se déclenche pendant la création de la poste.


1
Parfois, l' post_date_gmtest 2019-03-12 01:31:30et l' post_modified_gmtest 2019-03-12 01:31:31. :(
He Yifei 何 一 非

1
@HeYifei 何 一 非 bon point, si le traitement commence à la fin d'une seconde donnée, cela pourrait arriver. J'ai mis à jour ma réponse, merci
James Cushing

Les gars, juste une info. Le crochet est déclenché lors de la restauration et de la suppression d'un message.
melvin

6

J'ai fini par vérifier l'existence d'une valeur personnalisée avant de la définir. De cette façon, s'il s'agit d'une publication nouvellement créée, la valeur personnalisée n'existerait pas encore.

function attributes_save_postdata($post_id) {
  if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
  if (!wp_verify_nonce($_POST['_attributes_noncename'], plugin_basename(__FILE__))) return;
  if ('page' == $_POST['post_type']) {
    if (!current_user_can('edit_page', $post_id)) return;
  } else {
    if (!current_user_can('edit_post', $post_id)) return;
  }
  $termid = get_post_meta($post_id, '_termid', true);
  if ($termid != '') {
    // it's a new record
    $termid = 'update';
  } else {
    // it's an existing record
  }
  update_post_meta($post_id, '_termid', $termid);
}
add_action('save_post', 'attributes_save_postdata');

Pour que cela fonctionne, devez-vous d'abord créer le champ personnalisé à l'aide de add_post_meta?
MF1

Selon le Codex: [update_post_meta] peut être utilisé à la place de la fonction add_post_meta (). codex.wordpress.org/Function_Reference/update_post_meta
hereswhatidid

Cela peut échouer si des publications ont été créées avant l'activation du hook de code via une activation de plug-in. Les publications plus anciennes n'ont pas le méta-set, donc la première mise à jour pour elles sera considérée comme nouvelle.
Vasu Chawla

4

Exemple de réponse à l'ialocine avec le paramètre "mise à jour":

function save_func($ID, $post,$update) {

   if($update == false) {
     // do something if its first time publish
   } else {
     // Do something if its update
   }
}

add_action( 'save_post', 'save_func', 10, 3 );

2
Une meilleure façon de structurer cela serait soit de mettre le bloc de mise à jour en premier, permettant de faire simplement if($update)ou de garder le nouveau bloc en premier mais en utilisant if( ! $update ). Ce dernier mettra l'OP en meilleure pratique et est préféré à votre méthode par les normes de codage WordPress dans des cas comme l' opérateur ternaire
James Cushing

1

Vous pouvez utiliser le crochet d'action pre_post_update pour le code de mise à jour et save_post pour le nouveau code postal. Cela fonctionne avant la mise à jour d'un article.


4
save_postle crochet est déclenché à la fois lorsqu'un article est créé et mis à jour (après que WordPress l'a enregistré dans la base de données). pre_post_updateest renvoyé lorsqu'un article est mis à jour, mais avant sa mise à jour - cela peut être important.
Stephen Harris

1

Comme Darshan Thanki l'a laissé entendre (et Stephen Harris a précisé), vous pouvez utiliser pre_post_updateà votre avantage.

global $___new_post;
$___new_post = true;

add_action(
  'pre_post_update',
  function() {
    global $___new_post;
    $___new_post = false;
  },
  0
);

function is_new_post() {
  global $___new_post;
  return $___new_post;
}

La raison pour laquelle j'ai utilisé des globaux est parce que function is_new_post() use ( &$new_post )n'est pas valide en PHP (choquant ...) donc tirer cette variable dans la portée de la fonction ne fonctionne pas - d'où le global.

Notez que cela ne peut vraiment être utilisé de manière fiable que pendant / après l' save_postévénement (ce qui est généralement suffisant, au moins pour ce que nous en faisons).


0

Lorsque save_post est déclenché, toutes les informations sur cette publication sont déjà disponibles, donc en théorie, vous pouvez utiliser

function f4553265_check_post() {

    if (!get_posts($post_id)) {
    // if this is a new post get_posts($post_id) should return null
    } else {
    // $post_id already exists on the database
    }
}
add_action('save_post','f4553265_check_post');

ce n'est pas testé, cependant. =)


3
Au moment où vous arrivez au save_postmessage lui-même, il aurait déjà été enregistré dans la base de données - il en get_postsserait de même pour le message actuel.
Stephen Harris

C'est vrai, viens de le vérifier dans le Codex. Merci pour l'information.
moralida

0

Une autre approche qui utilise une fonction intégrée et aucun ajout à la base de données n'impliquerait get_post_status().

$post_status = get_post_status();
if ( $post_status != 'draft' ) {
    //draft
} else { 
    //not a draft: can be published, pending, etc. 
}

Notez cependant qu'il peut ne pas être approprié si vous envisagez de redéfinir ultérieurement le statut sur "brouillon" - vos instructions seront répétées la prochaine fois que vous mettrez à jour le message. Selon le contexte, vous souhaiterez peut-être prendre en compte les différentes chaînes qui peuvent être renvoyées par get_post_status()pour créer un scénario plus approprié.

Voir Codex pour get_post_status () et Post Status

Les valeurs possibles sont:

  • 'publier' - Une publication ou une page publiée
  • 'en attente' - la publication est en attente de révision
  • 'draft' - un poste en statut de brouillon
  • 'auto-draft' - un article nouvellement créé, sans contenu
  • 'future' - un article à publier dans le futur
  • «privé» - non visible pour les utilisateurs non connectés
  • «hériter» - une révision. voir get_children.
  • 'corbeille' - le message est dans la corbeille. ajouté avec la version 2.9.

Je ne pense pas que cela fasse ce qui a été demandé. Si je crée un nouveau message, puis que je clique sur «Publier», il save_post()est exécuté pour la première fois, mais pendant cette exécution, il get_post_status()renvoie déjà «publier» et non «brouillon», même s'il n'est qu'en cours de publication.
cgogolin
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.