Verifique la actualización versus la nueva publicación en la acción save_post

21

¿Es posible dentro de la acción save_post determinar si se está creando una nueva publicación o si se está actualizando una publicación existente?

hereswhatidid
fuente
No creo que esto sea posible. Vea mi comentario debajo de la respuesta de @ moraleida. ¿Por qué necesita saber si se trata de una nueva publicación o se está actualizando? Puede haber una solución alternativa o un enfoque alternativo.
Stephen Harris

Respuestas:

16

Desde WordPress versión 3.7. - IIRC - el save_postgancho - más información sobre el gancho y su uso en Code Reference:save_post y Codex:save_post - tiene un tercer parámetro $updateque puede usarse para determinar exactamente eso.

@param int $ post_ID ID de publicación.
@param WP_Post $ post Publicar objeto.
@param bool $ update Si esta es una publicación existente que se está actualizando o no.


Nota:

$updateno siempre es así true: puede verlo y probarlo usted mismo con el siguiente código. Sin embargo, no está bien documentado, posiblemente lejos de tener un nombre óptimo y, por lo tanto, crea expectativas engañosas. El siguiente código se puede usar para algunas depuraciones, juegue con cuándo interceptar la ejecución del código, porque de lo contrario no verá la información / mensajes. Creo que el culpable del comportamiento engañoso es el manejo de revisiones y guardados automáticos, que podrían desactivarse, pero no lo recomiendo y no lo he probado. No estoy seguro de si esto justifica un ticket de Trac , así que no abrí uno, si lo cree, siga el enlace y hágalo usted mismo. Aparte de eso, como se indica en los comentarios, si tiene un problema específico, publique una nueva pregunta.

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
fuente
3
El $updateparámetro SIEMPRE es verdadero incluso cuando se trata de una nueva publicación. Entonces este parámetro es inútil. No estoy seguro de si alguna vez funcionó, pero de seguro no funciona de la manera que está documentada en la última versión de WordPress 4.8.
Solomon Closson
@SolomonClosson Si echas un vistazo wp_publish_post, entonces sí. Pero eso no es cierto para su uso en wp_insert_post. He escrito una función de depuración, la agrego a la respuesta.
Nicolai
@SolomonClosson Si tiene un problema concreto real, haga una nueva pregunta. Eche un vistazo a las revisiones de la función de depuración y una explicación.
Nicolai
El save_postgancho tiene un tercer parámetro que siempre se establece en VERDADERO, por lo que no estoy seguro de qué tiene que ver con otros ganchos, sin hablar de otros ganchos. Estoy hablando del gancho en tu respuesta. Esto es incorrecto.
Solomon Closson
@SolomonClosson Como dije, el gancho está ocurriendo dos veces: wp_insert_post(), wp_publish_post(). Este último es solo publicaciones futuras, $updateestá configurado para ser siempre true. De lo contrario, en lo que respecta wp_insert_post(), $updateno es siempre true.
Nicolai
11

La forma en que realizo esta verificación (dentro de una función enganchada) es comparar la fecha de publicación y la fecha de modificación (en GMT para la estandarización)

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' );

Esto funciona porque incluso en la creación, la publicación tiene una fecha 'modificada' adjunta, que es exactamente la misma que la fecha 'creada', pero permitimos una variación de 1 segundo en cualquier caso en caso de que un segundo marque durante la creación de el cargo.

James Cushing
fuente
1
A veces el post_date_gmtes 2019-03-12 01:31:30y el post_modified_gmtes 2019-03-12 01:31:31. :(
He Yifei 何 一 非
1
@HeYifei 何 一 非 buen punto, si el procesamiento comienza al final de un segundo dado, esto podría suceder. He actualizado mi respuesta, gracias
James Cushing
Chicos, solo una información. El gancho se activa al restaurar y eliminar una publicación.
Melvin
6

Terminé simplemente comprobando la existencia de un valor personalizado antes de configurarlo. De esa manera, si se trata de una publicación recién creada, el valor personalizado aún no existiría.

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
fuente
Para que esto funcione, ¿primero debe crear el campo personalizado con add_post_meta?
MF1
Según el Codex: [update_post_meta] puede usarse en lugar de la función add_post_meta (). codex.wordpress.org/Function_Reference/update_post_meta
hereswhatidid
Esto podría fallar si las publicaciones se crearon antes de que el enlace de código se habilite a través de la activación de un complemento. Las publicaciones más antiguas no tienen el meta conjunto, por lo tanto, la primera actualización para ellas se considerará como nueva.
Vasu Chawla
4

Ejemplo de respuesta de ialocina con paremeter "update":

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
fuente
2
Una mejor manera de estructurar esto sería poner primero el bloque de actualización, permitiendo simplemente hacer if($update)o mantener el nuevo bloque primero pero usando if( ! $update ). Este último llevará a OP a una mejor práctica y es preferible a su método por los estándares de codificación de WordPress en casos como el operador ternario
James Cushing
1

Puede usar el enlace de acción pre_post_update para el código de actualización y save_post para el nuevo código postal. Funciona antes de que se actualice una publicación.

Darshan Thanki
fuente
44
save_postgancho se disparó tanto cuando se crea un poste y actualiza (después de WordPress se ha guardado en la base de datos). pre_post_updatese activa cuando se actualiza una publicación, pero antes de que se actualice, esto puede ser importante.
Stephen Harris el
1

Como Darshan Thanki insinuó (y Stephen Harris dio más detalles), puede utilizarlo pre_post_updatepara su ventaja.

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 razón por la que usé globals es porque function is_new_post() use ( &$new_post ) no es válido en PHP (impactante ...), por lo que incorporar esa variable en el alcance de la función no funciona, de ahí el global.

Tenga en cuenta que esto realmente solo se puede usar de manera confiable dentro / después del save_postevento (que generalmente es suficiente, al menos para lo que estamos haciendo con él).

Qix
fuente
0

Cuando se activa save_post, toda la información sobre esa publicación ya está disponible, por lo que, en teoría, podría usar

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');

Sin embargo, esto no ha sido probado. =)

moraleida
fuente
3
En el momento en que llegue a save_postla publicación en sí, ya se habría guardado en la base de datos, por get_postslo que devolvería la publicación actual.
Stephen Harris
Es cierto, acabo de comprobarlo en el Codex. Gracias por el aviso.
moraleida
0

Otro enfoque que utiliza una función incorporada y no implicaría ninguna adición a la base de datos get_post_status().

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

Sin embargo, tenga en cuenta que es posible que no sea apropiado si luego planea volver a establecer el estado en "borrador"; sus instrucciones se repetirán la próxima vez que actualice la publicación. Dependiendo del contexto, es posible que desee considerar las diversas cadenas que puede devolver get_post_status()para crear un escenario más apropiado.

Ver Codex para get_post_status () y estado de publicación

Los valores posibles son:

  • 'publicar': una publicación o página publicada
  • 'pendiente': la publicación está pendiente de revisión
  • 'borrador': una publicación en estado de borrador
  • 'borrador automático': una publicación recién creada, sin contenido
  • 'futuro' - una publicación para publicar en el futuro
  • 'privado': no ​​visible para los usuarios que no han iniciado sesión
  • 'heredar': una revisión. ver get_children.
  • 'basura': la publicación está en la papelera. agregado con la versión 2.9.
Juan112
fuente
No creo que esto haga lo que se le pidió. Si creo una nueva publicación y luego presiono 'Publicar', save_post()se ejecuta por primera vez, pero durante esa ejecución get_post_status()ya devuelve 'publicar' y no 'borrador', aunque solo esté en proceso de publicación.
cgogolin