Adiciona validação e tratamento de erros ao salvar campos personalizados?

28

Eu tenho uma função que define um campo personalizado em um tipo de postagem. Diga que o campo é "subtítulo".

Quando a postagem é salva, desejo fazer alguma validação na entrada e exibir uma mensagem de erro na tela de edição de postagem, se necessário. Algo como:

// Handle post updating
function wpse_update_post_custom_values($post_id, $post) {

    // Do some checking...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors->add('oops', 'There was an error.');

    }

    return $errors;

} 
add_action('save_post','wpse_update_post_custom_values',1,2);

Estou tentando ligar isso à ação save_post, mas não consigo descobrir como lidar com erros. Não parece haver um objeto de erro passado para a função, e se eu criar meu próprio obj WP_Error e retorná-lo, ele não será respeitado por qualquer mecanismo que gere erros na página de edição de postagem.

Atualmente, tenho uma mensagem de erro na página dentro da minha meta box customizada, mas isso é menos que ideal - prefiro ter um erro grande, vermelho, como o WP normalmente exibe. / p>

Alguma idéia?

ATUALIZAÇÃO:

Com base na resposta do @Denis, tentei algumas coisas diferentes. Armazenar erros como globais não funcionou, porque o Wordpress faz um redirecionamento durante o processo save_post, que mata o global antes que você possa exibi-lo.

Acabei por armazená-los em um meta-campo. O problema é que você precisa apagá-los, ou eles não desaparecem quando você navega para outra página, então eu tive que adicionar outra função anexada ao admin_footer que apenas limpa os erros.

Eu não esperava que o tratamento de erros para algo tão comum (postagens atualizadas) fosse tão desajeitado. Estou faltando alguma coisa óbvia ou esta é a melhor abordagem?

// Handle post updating
function wpse_5102_update_post_custom_values($post_id, $post) {

    // To keep the errors in
    $errors = false;

    // Do some validation...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors .= 'whoops...there was an error.';

    }

    update_option('my_admin_errors', $errors);

    return;

} 
add_action('save_post','wpse_5102_update_post_custom_values',1,2);


// Display any errors
function wpse_5102_admin_notice_handler() {

    $errors = get_option('my_admin_errors');

    if($errors) {

        echo '<div class="error"><p>' . $errors . '</p></div>';

    }   

}
add_action( 'admin_notices', 'wpse_5102_admin_notice_handler' );


// Clear any errors
function wpse_5102__clear_errors() {

    update_option('my_admin_errors', false);

}
add_action( 'admin_footer', 'wpse_5102_clear_errors' );
    
por MathSmath 09.12.2010 / 22:57
fonte

7 respostas

7

Armazene erros em sua classe ou como globais, possivelmente em um transiente ou meta, e exiba-os em avisos de administrador sobre solicitações POST. O WP não possui nenhum manipulador de mensagens flash.

    
por Denis de Bernardy 09.12.2010 / 23:02
fonte
6

Eu sugiro usar sessões, pois isso não criará efeitos estranhos quando dois usuários editarem ao mesmo tempo. Então é isso que eu faço:

As sessões não são iniciadas pelo wordpress. Então você precisa iniciar uma sessão em seu plugin, functions.php ou até wp-config .php:

if (!session_id())
  session_start();

Ao salvar a postagem, acrescente erros e avisos à sessão:

function my_save_post($post_id, $post) {
   if($something_went_wrong) {
     //Append error notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="error"><p>This or that went wrong</p></div>';
     return false; //might stop processing here
   }
   if($somthing_to_notice) {  //i.e. successful saving
     //Append notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="updated"><p>Post updated</p></div>';
   }

   return true;
} 
add_action('save_post','my_save_post');

Imprima avisos e erros e limpe as mensagens na sessão:

function my_admin_notices(){
  if(!empty($_SESSION['my_admin_notices'])) print  $_SESSION['my_admin_notices'];
  unset ($_SESSION['my_admin_notices']);
}
add_action( 'admin_notices', 'my_admin_notices' );
    
por davidn 14.06.2011 / 12:36
fonte
5

Baseado em pospi 's sugestão para usar transientes , eu vim com o seguinte. O único problema é que não há nenhum hook para colocar a mensagem abaixo do h2 onde outras mensagens vão, então eu tive que fazer um jQuery hack para chegar lá.

Primeiro, salve a mensagem de erro do manipulador save_post (ou semelhante). Eu dou a ele uma vida curta de 60 segundos, então é só o suficiente para o redirecionamento acontecer.

if($has_error)
{
  set_transient( "acme_plugin_error_msg_$post_id", $error_msg, 60 );
}

Em seguida, recupere a mensagem de erro no próximo carregamento da página e exiba-a. Eu também apago para que não seja exibido duas vezes.

add_action('admin_notices', 'acme_plugin_show_messages');

function acme_plugin_show_messages()
{
  global $post;
  if ( false !== ( $msg = get_transient( "acme_plugin_error_msg_{$post->ID}" ) ) && $msg) {
    delete_transient( "acme_plugin_error_msg_{$post->ID}" );
    echo "<div id=\"acme-plugin-message\" class=\"error below-h2\"><p>$msg</p></div>";
  }
}

Como admin_notices é disparado antes que o conteúdo da página principal seja gerado, o aviso não é para onde as outras mensagens de edição de postagem vão, então eu tive que usar este jQuery para movê-lo para lá:

jQuery('h2').after(jQuery('#acme-plugin-message'));

Como o ID do post faz parte do nome do transiente, isso deve funcionar na maioria dos ambientes de vários usuários, exceto quando vários usuários estão editando simultaneamente o mesmo post.

    
por Joshua Coady 15.09.2012 / 23:55
fonte
1

Por que você não valida seu campo com a ajuda de algum Javascript? Eu acho que essa seria a melhor abordagem para isso.

    
por Horttcore 10.12.2010 / 09:10
fonte
1

Tentando usar o script acima, me deparei com um problema estranho. Duas mensagens são mostradas na tela de edição, após a atualização do post. Um está mostrando o estado do conteúdo do save anterior e outro do atual. Por exemplo, se eu salvar a postagem corretamente e, em seguida, cometer um erro, a primeira é "erro" e a segunda é "ok" - embora sejam geradas no mesmo tempo. Se eu alterar o script e anexar apenas uma mensagem (por exemplo, "erro"), inicie uma atualização com "erro" e depois a outra com a mensagem "ok", "erro" permanece (é exibida pela segunda vez). Eu devo salvar com "ok" mais uma vez para me livrar dele. Eu realmente não sei o que está errado, eu testei em três servidores locais diferentes e há o mesmo problema em cada um deles. Se alguém tiver alguma ideia ou sugestão, por favor ajude!

    
por jlub 08.09.2011 / 18:57
fonte
1

Quando save_post é executado, ele já salvou a postagem no banco de dados.

Examinando o código principal do WordPress, mais especificamente na função wp-includes/post.php update_post() , não há nenhuma maneira interna de interceptar uma solicitação antes que ela seja salva no banco de dados.

No entanto, podemos ligar pre_post_update e usar header() e get_post_edit_link() para impedir que a postagem seja salva.

<?php

/**
*   Performs custom validation on custom post type "Site"
*/
function custom_post_site_save($post_id, $post_data) {
    # If this is just a revision, don't do anything.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'site') {
        # In this example, we will deny post titles with less than 5 characters
        if (strlen($post_data['post_title'] < 5)) {
            # Add a notification
            update_option('my_notifications', json_encode(array('error', 'Post title can\'t be less than 5 characters.')));
            # And redirect
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

/**
*   Shows custom notifications on wordpress admin panel
*/
function my_notification() {
    $notifications = get_option('my_notifications');

    if (!empty($notifications)) {
        $notifications = json_decode($notifications);
        #notifications[0] = (string) Type of notification: error, updated or update-nag
        #notifications[1] = (string) Message
        #notifications[2] = (boolean) is_dismissible?
        switch ($notifications[0]) {
            case 'error': # red
            case 'updated': # green
            case 'update-nag': # ?
                $class = $notifications[0];
                break;
            default:
                # Defaults to error just in case
                $class = 'error';
                break;
        }

        $is_dismissable = '';
        if (isset($notifications[2]) && $notifications[2] == true)
            $is_dismissable = 'is_dismissable';

        echo '<div class="'.$class.' notice '.$is_dismissable.'">';
           echo '<p>'.$notifications[1].'</p>';
        echo '</div>';

        # Let's reset the notification
        update_option('my_notifications', false);
    }
}
add_action( 'admin_notices', 'my_notification' );
    
por Lucas Bustamante 29.07.2018 / 23:54
fonte
0

Eu escrevi um plug-in que adiciona um erro de flash para as telas de pós-edição e impede que as postagens sejam publicadas até que os campos obrigatórios sejam preenchidos:

enlace

Ele permite que qualquer campo de postagem seja obrigatório, mas você pode usar a API que ele fornece para tornar necessários também os campos personalizados com uma mensagem de erro e função de validação personalizáveis. O padrão é verificar se o campo está vazio ou não.

    
por sanchothefat 19.11.2012 / 11:00
fonte