Verifique se há atualização vs nova postagem na ação save_post

21

É possível, dentro da ação save_post, determinar se é uma nova postagem sendo criada ou uma postagem existente sendo atualizada?

hereswhatidid
fonte
Eu não acho que isso seja possível. Veja o meu comentário abaixo da resposta da @ moraleida. Por que você precisa saber se é uma nova postagem ou está sendo atualizada? Pode haver uma solução alternativa ou uma abordagem alternativa.
21712 Stephen

Respostas:

16

Desde a versão 3.7 do WordPress. - IIRC - o save_postgancho - mais informações sobre o gancho e seu uso em Referência de Código:save_post e Codex:save_post - possui um terceiro parâmetro $updateque pode ser usado para determinar exatamente isso.

@param int $ post_ID ID da postagem.
@param WP_Post $ post Objeto Post.
@param bool $ update Se esta é uma publicação existente que está sendo atualizada ou não.


Nota:

$updatenem sempre é possível true- você pode ver e testar você mesmo com o código abaixo. No entanto, ele não está bem documentado, possivelmente longe de ser o ideal, e, portanto, cria expectativas enganosas. O código abaixo pode ser usado para alguma depuração, brinque com quando interceptar a execução do código, porque, caso contrário, você não verá as informações / mensagens. Penso que o culpado de comportamento enganoso é o tratamento de revisões e salvamentos automáticos - que podem ser desativados, mas eu não recomendo e ainda não os testei. Não tenho certeza se isso merece um bilhete Trac , então eu não abri um, se você acha, siga o link e faça você mesmo. Além disso, conforme declarado nos comentários, se você tiver um problema específico, poste uma nova pergunta.

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
fonte
3
O $updateparâmetro SEMPRE é verdadeiro mesmo quando é uma nova postagem. Portanto, este parâmetro é inútil. Não tenho certeza se alguma vez funcionou, mas com certeza não está funcionando da maneira que está documentada na versão mais recente do wordpress 4.8.
Solomon Closson
@SolomonClosson Se você der uma olhada wp_publish_post, então sim. Mas isso não é verdade para seu uso no wp_insert_post. Eu escrevi uma função de depuração, adiciono-a à resposta.
Nicolai
@SolomonClosson Se você tiver um problema concreto real, faça uma nova pergunta. Dê uma olhada nas revisões da função de depuração e uma explicação.
Nicolai
O save_postgancho tem um terceiro parâmetro que é sempre definido como TRUE, portanto, não saiba o que isso tem a ver com outros ganchos, sem falar sobre outros ganchos. Estou falando do gancho na sua resposta. Isto está incorreto.
Solomon Closson
@SolomonClosson Como eu disse, o gancho está ocorrendo duas vezes: wp_insert_post(), wp_publish_post(). Este último é apenas posts futuros, $updateestá definido para ser sempre true. Caso contrário, no que diz respeito wp_insert_post(), $updatenem sempre é true.
Nicolai
11

A maneira como realizo essa verificação (dentro de uma função ligada) é comparar a data de postagem e a data de modificação (em GMT para padronização)

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

Isso funciona porque, mesmo na criação, a postagem tem uma data 'modificada' anexada a ela, que é exatamente a mesma que a data 'criada', mas permitimos uma variação de 1 segundo de qualquer maneira, caso um segundo passe durante a criação de o post.

James Cushing
fonte
1
Às vezes o post_date_gmté 2019-03-12 01:31:30e o post_modified_gmté 2019-03-12 01:31:31. :(
He Yifei 非 一 非 12/03
1
@HeYifei 非 一 非 bom ponto, se o processamento começar no final de um segundo, isso pode acontecer. Eu atualizei minha resposta, obrigado
James Cushing
Gente, apenas uma informação. O gancho é acionado ao restaurar e excluir uma postagem.
melvin
6

Acabei verificando a existência de um valor personalizado antes de defini-lo. Dessa forma, se for uma postagem recém-criada, o valor personalizado ainda não existiria.

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
fonte
Para que isso funcione, você precisa primeiro criar o campo personalizado usando add_post_meta?
MF1
De acordo com o Codex: [update_post_meta] pode ser usado no lugar da função add_post_meta (). codex.wordpress.org/Function_Reference/update_post_meta
hereswhatidid
Isso pode falhar, se as postagens foram criadas antes que o gancho de código seja ativado por meio da ativação de um plug-in. As postagens mais antigas não possuem o conjunto de meta, portanto, a primeira atualização para elas será considerada nova.
Vasu Chawla
4

Exemplo para resposta de ialocina com o parâmetro "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
fonte
2
Uma maneira melhor de estruturar isso seria colocar o bloco de atualização em primeiro lugar, permitindo apenas fazer if($update)ou manter o novo bloco em primeiro lugar, mas usando if( ! $update ). Este último terá OP em melhor prática e é preferido sobre o seu método pelo WordPress padrões de codificação em casos como o operador ternário
James Cushing
1

Você pode usar o gancho de ação pre_post_update para o código de atualização e save_post para o novo código postal. Funciona antes de uma postagem ser atualizada.

Darshan Thanki
fonte
4
save_postgancho é acionado tanto quando um post é criado e atualizado (após WordPress salvou-lo para o banco de dados). pre_post_updateé acionado quando uma postagem é atualizada, mas antes da atualização, isso pode ser importante.
Stephen Harris
1

Como Darshan Thanki sugeriu (e Stephen Harris elaborou mais adiante), você pode usar pre_post_updatea seu favor.

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

A razão pela qual eu usei globals é porque function is_new_post() use ( &$new_post )não é válido em PHP (chocante ...), portanto, puxar essa variável para o escopo da função não funciona - daí o global.

Observe que isso só pode ser usado de maneira confiável dentro / após o save_postevento (o que geralmente é suficiente, pelo menos para o que estamos fazendo com ele).

Qix
fonte
0

Quando save_post é acionado, todas as informações sobre essa postagem já estão disponíveis; portanto, em teoria, você pode 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');

isso não foi testado, no entanto. =)

moraleida
fonte
3
No momento em que você chega à save_postpostagem, ela já estará salva no banco de dados - get_postsretornando a postagem atual.
21712 Stephen
É verdade, apenas verifiquei no Codex. Obrigado pelo aviso.
Moraleida 12/04/12
0

Outra abordagem que usa uma função interna e nenhuma adição ao banco de dados envolveria get_post_status().

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

Observe, no entanto, que talvez não seja apropriado se você planeja definir o status novamente como "rascunho" - suas instruções serão repetidas na próxima vez que você atualizar a postagem. Dependendo do contexto, convém considerar as várias cadeias que podem ser retornadas get_post_status()para criar um cenário mais apropriado.

Veja Codex para obter get_post_status () e Status da postagem

Os valores possíveis são:

  • 'publicar' - uma postagem ou página publicada
  • 'pendente' - a publicação está com revisão pendente
  • 'rascunho' - uma postagem no status de rascunho
  • 'rascunho automático' - uma postagem recém-criada, sem conteúdo
  • 'futuro' - um post para publicar no futuro
  • 'privado' - não visível para usuários que não estão conectados
  • 'herdar' - uma revisão. veja get_children.
  • 'lixeira' - a postagem está na lixeira. adicionado com a versão 2.9.
John112
fonte
Eu não acho que isso faz o que foi pedido. Se eu criar uma nova postagem e clicar em 'Publicar', save_post()é executado pela primeira vez, mas durante essa execução get_post_status()já retorna 'publicar' e não 'rascunho', mesmo que seja apenas no processo de publicação.
Cgogolin