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?

hereswhatidid
la source
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();
}
Nicolai
la source
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.

James Cushing
la source
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');
hereswhatidid
la source
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 );
Goran Jakovljevic
la source
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.

Darshan Thanki
la source
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).

Qix
la source
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. =)

Moralida
la source
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.
John112
la source
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