Comprobar actualización vs nueva entrada en la acción save_post

11 abr 2012, 22:43:16
Vistas: 42K
Votos: 25

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

1
Comentarios

No creo que esto sea posible. Mira mi comentario debajo de la respuesta de @moraleida. ¿Por qué necesitas saber si es una publicación nueva o se está actualizando? Puede haber una solución alternativa o un enfoque diferente.

Stephen Harris Stephen Harris
12 abr 2012 21:28:38
Todas las respuestas a la pregunta 13
7
20

Desde la versión 3.7 de WordPress - si mal no recuerdo - el hook save_post - más información sobre el hook y su uso en Referencia de Código: save_post y Codex: save_post - tiene un tercer parámetro $update que puede usarse para determinar precisamente eso.

@param     int               $post_ID     ID del Post.
@param     WP_Post     $post          Objeto del Post.
@param     bool            $update     Indica si es una actualización de un post existente o no.


Nota:

$update no siempre es true – puedes verlo y probarlo tú mismo con el código de abajo. Sin embargo, no está bien documentado, posiblemente el nombre no es óptimo y por lo tanto crea expectativas engañosas. El siguiente código puede usarse para depurar, juega con cuándo interceptar la ejecución del código, porque de lo contrario no verás los mensajes/información. Creo que el culpable del comportamiento engañoso es el manejo de revisiones y auto guardados – los cuales podrían desactivarse, pero no lo recomiendo y no lo he probado. No estoy seguro si esto amerita un Ticket en Trac, así que no abrí uno, si crees que sí, por favor sigue el enlace y hazlo tú mismo. Aparte de eso, como se menciona en los comentarios, si tienes un problema específico, publica 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';

  //condiciones
  if( ! $update && $post->post_status == "auto-draft" ) {
    // aplica a un post nuevo
    echo ' && $post->post_status == "auto-draft"';
    //die();
  } else if ( ! $update ) {
    // aplica básicamente a la revisión (auto guardada)
    //die();
  } else {
    // aplica a actualizar un post publicado
    // cuando hay una revisión, que es lo normal, 
    // comportamiento estándar de WordPress, entonces se considera 
    // una actualización, que es donde surge la confusión
    // hay otros métodos, como verificar el tiempo o el estado del post
    // dependiendo de tu caso de uso podría ser más apropiado 
    // usar alguna de esas alternativas 
    //die();
  }

  echo '</pre>';
  //die();
}
1 may 2015 00:13:02
Comentarios

El parámetro $update es SIEMPRE verdadero incluso cuando es una publicación nueva. Por lo tanto, este parámetro es inútil. No estoy seguro de si alguna vez funcionó, pero definitivamente no está funcionando como está documentado en la última versión de WordPress 4.8.

Solomon Closson Solomon Closson
20 jul 2017 23:32:34

@SolomonClosson Si miras 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 Grossherr Nicolai Grossherr
21 jul 2017 03:11:55

@SolomonClosson Si tienes un problema concreto real, por favor haz una nueva pregunta. Echa un vistazo a las revisiones de la función de depuración para obtener una explicación.

Nicolai Grossherr Nicolai Grossherr
21 jul 2017 03:34:11

El hook save_post tiene un tercer parámetro que siempre está establecido como TRUE, así que no estoy seguro de qué tiene que ver con otros hooks, no estoy hablando de otros hooks. Me refiero al hook en tu respuesta. Esto es incorrecto.

Solomon Closson Solomon Closson
24 jul 2017 02:42:42

@SolomonClosson Como dije, el hook ocurre dos veces: wp_insert_post(), wp_publish_post(). Este último es solo para posts programados, ahí $update siempre se establece como true. Por otro lado, en relación a wp_insert_post(), $update no siempre es true.

Nicolai Grossherr Nicolai Grossherr
24 jul 2017 16:08:09

Llego tarde a la fiesta, pero bueno, ¿por qué no? @Nicolai, lo que dices es lo que uno esperaría que ocurriera, pero no logro que $update sea false incluso cuando uso el hook 'wp_insert_post'. No importa dónde lo enganche, siempre es true. No entiendo por qué esto no está corregido.

Caio Mar Caio Mar
2 feb 2019 16:33:08

Chicos, solo una información. El hook se activa al restaurar y eliminar una publicación.

melvin melvin
9 may 2019 14:39:48
Mostrar los 2 comentarios restantes
6
13

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 estandarización)

function check_new_vs_update( $post_id ){
    $myPost     = get_post($post_id);
    $created    = new DateTime( $myPost->post_date_gmt );
    $modified   = new DateTime( $myPost->post_modified_gmt );
    $diff       = $created->diff( $modified );
    $seconds_difference = ((($diff->y * 365.25 + $diff->m * 30 + $diff->d) * 24 + $diff->h) * 60 + $diff->i)*60 + $diff->s;

    if( $seconds_difference <= 1 ){
        // Nueva publicación
    }else{
        // Publicación actualizada
    }
}
add_action('save_post', 'check_new_vs_update' );

Esto funciona porque incluso al crear la publicación, esta tiene una fecha de 'modificación' adjunta, que es exactamente igual a la fecha de 'creación', pero permitimos una variación de 1 segundo en caso de que pase un segundo durante la creación de la publicación.

10 feb 2015 15:51:45
Comentarios

A veces el post_date_gmt es 2019-03-12 01:31:30 y el post_modified_gmt es 2019-03-12 01:31:31. :(

He Yifei 何一非 He Yifei 何一非
12 mar 2019 06:06:47

@HeYifei何一非 buen punto, si el procesamiento comienza al final de un segundo dado, esto podría pasar. He actualizado mi respuesta, gracias

Cush Cush
12 mar 2019 15:04:13

Chicos, solo una info. El hook se dispara al restaurar y eliminar una entrada.

melvin melvin
9 may 2019 14:39:53

Bueno saberlo @melvin, gracias

Cush Cush
17 ago 2020 20:43:30

No puedo creer que tenga que ser tan complicado. WordPress nunca deja de sorprenderme.

amarinediary amarinediary
4 ene 2021 15:29:19

Para ser justos con ellos, tienen literalmente millones de usuarios y es un proyecto de código abierto. Desafortunadamente no pueden incluir cada característica y esta probablemente no es una de las más utilizadas. En años recientes cosas como mejorar el editor y la seguridad han sido priorizadas ¡y eso es bueno! ¡Quiero decir, incluso jQuery está siendo actualizado recién ahora! ¡Hasta la versión actual estaba corriendo 1.x!

Cush Cush
21 ene 2021 15:26:35
Mostrar los 1 comentarios restantes
4

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

function attributes_save_postdata($post_id) {
  // Verifica si es un guardado automático y salir si es así
  if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
  // Verifica el nonce de seguridad
  if (!wp_verify_nonce($_POST['_attributes_noncename'], plugin_basename(__FILE__))) return;
  // Verifica permisos para páginas o posts
  if ('page' == $_POST['post_type']) {
    if (!current_user_can('edit_page', $post_id)) return;
  } else {
    if (!current_user_can('edit_post', $post_id)) return;
  }
  // Obtiene el meta valor existente
  $termid = get_post_meta($post_id, '_termid', true);
  if ($termid != '') {
    // Es un nuevo registro
    $termid = 'update';
  } else {
    // Es un registro existente
  }
  // Actualiza el meta valor
  update_post_meta($post_id, '_termid', $termid);
}
// Añade la acción para guardar los datos
add_action('save_post', 'attributes_save_postdata');
18 abr 2012 00:50:50
Comentarios

¿Para que esto funcione, primero debes crear el campo personalizado usando add_post_meta?

MF1 MF1
9 abr 2013 05:03:17

Según el Codex: [update_post_meta] puede usarse en lugar de la función add_post_meta(). http://codex.wordpress.org/Function_Reference/update_post_meta

hereswhatidid hereswhatidid
20 ene 2014 23:46:08

Esto podría fallar si los posts fueron creados antes de que el código se active mediante la activación de un plugin. Los posts más antiguos no tienen el meta configurado, por lo que la primera actualización para ellos se considerará como nueva.

Vasu Chawla Vasu Chawla
5 may 2018 22:13:01

@VasuChawla entonces en ese caso quizás sea más confiable verificar la existencia isset() (por ejemplo) de ese término meta específico en lugar de si es verdadero o falso. Como una tercera condición. (if, elseif, ...else)

Viktor Borítás Viktor Borítás
1 ago 2020 20:03:44
1

Ejemplo de respuesta a ialocin con el parámetro "update":

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

   if($update == false) {
     // hacer algo si es la primera publicación
   } else {
     // Hacer algo si es una actualización
   }
}

add_action( 'save_post', 'save_func', 10, 3 );
1 dic 2015 19:53:53
Comentarios

Una mejor manera de estructurar esto sería colocando primero el bloque de actualización, permitiendo simplemente hacer if($update) o mantener primero el bloque nuevo pero usando if( ! $update ). Este último llevará al OP a mejores prácticas y es preferido sobre tu método según los estándares de codificación de WordPress en casos como el operador ternario

Cush Cush
17 nov 2016 13:38:30
0

Acabo de encontrarme con el save_post sobre nuevas publicaciones y actualizaciones. Después de leer el código fuente para entender el flujo, encontré que el siguiente método podría ser útil. Como aún no se ha mencionado antes, vean si les sirve a alguien. (La prueba es con Core 5.3.3)

El flujo de creación de una publicación es aproximadamente:

  1. Después de presionar "Añadir nueva" (Entrada)
  2. Se llamará a $post = get_default_post_to_edit( $post_type, true ); donde
  3. get_default_post_to_edit() recibe el argumento $create_in_db = true
  4. Así que wp_insert_post() se llama inmediatamente, se crea un borrador automático (auto-draft), incluso si no se guarda. Cada vez que se hace clic en "Añadir nueva", se crea un auto-draft
  5. $update siempre es verdadero para Publicar. Entonces, al publicar una nueva entrada, es verdadero.

Al comparar el objeto $_POST para una nueva entrada y una entrada actualizada o republicada, la diferencia prominente es el valor de _wp_http_referer, donde la nueva entrada es /wp-admin/post-new.php

Suposición: se asume que la entrada se publica/añade desde la interfaz de usuario. Si se hace por otro mecanismo o código personalizado, se necesitará ajustar la verificación.

add_action( 'save_post', 'test_save_post_check', 0, 3 );
function test_save_post_check( $post_ID, $post, $update ) {
    // otras pruebas + esta
    // verificando la posición 'post-new' en '_wp_http_referer'
    if( strpos( wp_get_raw_referer(), 'post-new' ) > 0 ) {
        // nueva
    } else {
        // actualización
    }
}
3 may 2020 18:14:40
0

aquí hay un código funcional que probé y usé en mi sitio web, que resuelve los siguientes dos problemas asociados con la acción save_post:

  1. problema para verificar entre actualización o inserción

  2. problema de inserción doble por la acción save_post

    function save_annonces_callback($post_ID, $post, $update){
    
            $post_type = get_post_type($post_ID);
    
            if ( $post_type === 'annonces' ){
    
                //esto previene la inserción doble por la acción save_post :)
                if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
                    return;
                } else {
    
                    //verificar si es un nuevo post para insertar
                    if( strpos( wp_get_raw_referer(), 'post-new' ) > 0 ){
    
                        //realizar inserción
    
                    }else{
    
                        //realizar actualización
                    }
    
                }
    
            }
        }add_action('save_post','save_annonces_callback', 10, 3);
    
14 jul 2021 19:34:25
1

Puedes usar el hook de acción pre_post_update para el código de actualización y save_post para el código de nuevo post. Funciona antes de que un post sea actualizado.

6 ago 2012 15:08:44
Comentarios

El hook save_post se activa tanto cuando se crea un post como cuando se actualiza (después de que WordPress lo haya guardado en la base de datos). pre_post_update se activa cuando un post se actualiza, pero antes de que el post sea actualizado - esto puede ser importante.

Stephen Harris Stephen Harris
12 ago 2012 21:59:39
0

Como sugirió Darshan Thanki (y Stephen Harris amplió), puedes aprovecharte del hook pre_post_update.

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é variables globales es porque function is_new_post() use ( &$new_post ) no es válido en PHP (sorprendente...) así que incorporar esa variable al ámbito de la función no funciona -- de ahí lo global.

Ten en cuenta que esto solo puede usarse de manera confiable dentro o después del evento save_post (lo cual suele ser suficiente, al menos para lo que estamos haciendo con ello).

6 ene 2015 22:49:27
3

Cuando se dispara save_post, toda la información sobre esa entrada ya está disponible, así que en teoría podrías usar:

function f4553265_check_post() {

    if (!get_posts($post_id)) {
    // si es una nueva entrada, get_posts($post_id) debería retornar null
    } else {
    // $post_id ya existe en la base de datos
    }
}
add_action('save_post','f4553265_check_post');

Esto no está probado, sin embargo. =)

12 abr 2012 07:27:21
Comentarios

Para cuando llegas a save_post, el post en sí ya se habría guardado en la base de datos - así que get_posts devolvería el post actual.

Stephen Harris Stephen Harris
12 abr 2012 21:25:41

Cierto, acabo de verificarlo en el Codex. Gracias por el aviso.

moraleida moraleida
12 abr 2012 21:59:38

Esto no funciona con get_posts pero sí funciona con get_post.

Gavin Gavin
18 ago 2020 05:28:49
1

Otro enfoque que utiliza una función incorporada y no requiere agregar nada a la base de datos sería usar get_post_status().

$post_status = get_post_status();
if ( $post_status != 'draft' ) {
    //borrador
} else { 
    //no es un borrador: puede ser publicado, pendiente, etc. 
}

Sin embargo, ten en cuenta que puede no ser apropiado si planeas establecer el estado nuevamente como "borrador" más tarde – tus instrucciones se repetirán la próxima vez que actualices la publicación. Dependiendo del contexto, podrías considerar las distintas cadenas que puede devolver get_post_status() para construir un escenario más adecuado.

Consulta el Codex para get_post_status() y Estado de la Publicación

Los valores posibles son:

  • 'publish' - Una publicación o página publicada
  • 'pending' - la publicación está pendiente de revisión
  • 'draft' - una publicación en estado de borrador
  • 'auto-draft' - una publicación recién creada, sin contenido
  • 'future' - una publicación programada para publicarse en el futuro
  • 'private' - no visible para usuarios no registrados
  • 'inherit' - una revisión. ver get_children.
  • 'trash' - la publicación está en la papelera. añadido en la Versión 2.9.
12 dic 2014 04:15:22
Comentarios

No creo que esto haga lo que se pidió. Si creo una nueva entrada y luego presiono 'Publicar', save_post() se ejecuta por primera vez, pero durante esa ejecución get_post_status() ya devuelve 'publish' y no 'draft', a pesar de que solo está en proceso de publicación.

cgogolin cgogolin
25 nov 2017 20:39:01
0

Dado que el parámetro $update es inútil, esta es la forma más rápida que probé:

function wpse48678_check_is_post_new($post_id, $post, $update)
{
    if (false !== strpos($_POST['_wp_http_referer'], 'post-new.php')) {
        return true; // O hacer algo más.
    } else {
        return false; // O hacer algo más.
    }
}
add_action('save_post_{$post_type}', 'wpse48678_check_is_post_new', 10, 3);
9 sept 2020 23:26:12
0

He pasado horas en esto

Actualmente estoy en proceso de desarrollar un plugin y quería enviar una notificación a todos los autores cuando una página era "Creada" en el sitio de mi Compañía de Diseño Web.

Originalmente intenté usar lo siguiente:

add_action('save_post_page', function($post_id, $post, $update) {
    if(!$update){
        echo("¡Es una publicación nueva!");
    }else{
        echo("¡Es una publicación antigua!");
    }
}

Seguía mostrando "¡Es una publicación antigua!". ¿Pero por qué??? Bueno, después de investigar un poco parece que después de hacer clic en el botón "Añadir nueva página" WordPress crea instantáneamente un auto-guardado que establece la variable $update como verdadera. Qué útil.

Después de horas de investigación finalmente encontré lo siguiente que funciona:

// Se activa cuando una publicación cambia de "estado", es decir, de pendiente a borrador, de publicado a programado.
add_action('transition_post_status', function($new_status, $old_status, $post) {
    // Comprueba si la publicación pasa de auto-guardado a cualquier otro estado (borrador, pendiente, publicado, etc.)
    if 'auto-draft' === $old_status && $new_status !== 'auto-draft'){
        echo("¡Es una publicación nueva!");
    }else{
        echo("¡Es una publicación antigua!");
    }
}

Nota: En WordPress, "borrador" y "auto-guardado" son diferentes. Un estado de "borrador" es una publicación que un usuario establece manualmente como borrador, lo que indica que está en progreso. Un "auto-guardado", por otro lado, se asigna automáticamente a una publicación cuando se crea pero aún no se ha publicado. Básicamente es otra forma de decir auto-guardado.

Espero que esto ayude a algunas personas... Ahora a pasar otras 4 horas con otro problema jaja.

12 dic 2024 22:45:17
0

Esto debería funcionar chicos

add_action( 'wp_after_insert_post', 'clearCDNCache', 10, 4);       
 
public function clearCDNCache($post_id, $post, $update, $post_before){
        
        if ( ! empty($_POST['_wpnonce']) ) {
            // Ejecutar función personalizada solo una vez
        }
    
        // Añadir nuevo modo.
        if (!empty($_POST['_wp_http_referer']) && $_POST['_wp_http_referer'] == '/wp-admin/post-new.php') { 

        } else {
            // Modo actualización
        }
       
    }
27 feb 2025 11:12:21