¿Agregar validación y manejo de errores al guardar campos personalizados?

28

Tengo una función que define un campo personalizado en un tipo de publicación. Digamos que el campo es "subtítulo".

Cuando se guarda la publicación, quiero hacer una validación en la entrada y mostrar un mensaje de error en la pantalla de edición de la publicación si es necesario. 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);

Estoy intentando enganchar esto a la acción save_post, pero no puedo entender cómo manejar los errores. No parece que se haya pasado un objeto de error a la función, y si creo mi propio WP_Error obj y lo devuelvo, no es respetado por ningún mecanismo que escupe errores en la página de edición de publicaciones.

Actualmente tengo un mensaje de error en la página dentro de mi meta caja personalizada, pero esto no es lo ideal. Prefiero tener un error grande, rojo, arriba como el de WP, como se muestra normalmente.

¿Alguna idea?

ACTUALIZAR :

Basado en la respuesta de @Denis, probé algunas cosas diferentes. El almacenamiento de errores como un global no funcionó, porque Wordpress redirecciona durante el proceso save_post, lo que mata al global antes de poder mostrarlo.

Terminé almacenándolos en un campo meta. El problema con esto es que necesitas borrarlos o no desaparecerán cuando navegues a otra página, así que tuve que agregar otra función adjunta al admin_footer que simplemente borra los errores.

No hubiera esperado que el manejo de errores para algo tan común (actualización de publicaciones) fuera tan torpe. ¿Me estoy perdiendo algo obvio o es este el mejor enfoque?

// 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' );
    
pregunta MathSmath 09.12.2010 - 22:57

7 respuestas

7

Almacene los errores en su clase o en forma global, posiblemente en un transitorio o meta, y muéstrelos en avisos de administrador en las solicitudes POST. WP no presenta ningún controlador de mensajes flash.

    
respondido por el Denis de Bernardy 09.12.2010 - 23:02
6

Sugiero utilizar sesiones, ya que esto no creará efectos extraños cuando dos usuarios editen al mismo tiempo. Así que esto es lo que hago:

Las sesiones no se inician con wordpress. Por lo tanto, debe iniciar una sesión en su complemento, functions.php o incluso wp-config .php:

if (!session_id())
  session_start();

Al guardar la publicación, agregue errores y avisos a la sesión:

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 y errores y luego limpie los mensajes en la sesión:

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' );
    
respondido por el davidn 14.06.2011 - 12:36
5

Basado en pospi 's sugerencia para usar transients , se me ocurrió lo siguiente. El único problema es que no hay ningún gancho para colocar el mensaje debajo del h2 donde van otros mensajes, así que tuve que hacer un hack jQuery para llegar allí.

Primero, guarde el mensaje de error durante su controlador save_post (o similar). Le doy una vida útil corta de 60 segundos, por lo que es suficiente para que se produzca la redirección.

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

Luego, simplemente recupere ese mensaje de error en la página siguiente y visualícelo. También lo elimino para que no se muestre dos veces.

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

Dado que admin_notices se dispara antes de que se genere el contenido de la página principal, el aviso no es donde van los otros mensajes posteriores a la edición, así que tuve que usar este jQuery para moverlo allí:

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

Dado que la ID de la publicación es parte del nombre transitorio, esto debería funcionar en la mayoría de los entornos multiusuario, excepto cuando varios usuarios editan simultáneamente la misma publicación.

    
respondido por el Joshua Coady 15.09.2012 - 23:55
1

¿Por qué no validas tu campo con la ayuda de algunos Javascript? Creo que este sería el mejor enfoque para esto.

    
respondido por el Horttcore 10.12.2010 - 09:10
1

Tratando de usar el script anterior, me encontré con un problema extraño. Dos mensajes se muestran en la pantalla de edición, después de la actualización posterior. Uno muestra el estado del contenido del guardado anterior y otro del actual. Por ejemplo, si guardo la publicación correctamente y luego cometo un error, el primero es "error" y el segundo "ok", aunque se generan al mismo tiempo. Si cambio la secuencia de comandos y agrego solo un mensaje (por ejemplo, "error"), inicie una actualización con "error" y luego otro con "ok", el mensaje "error" permanece (se muestra por segunda vez). Debo guardar con "ok" una vez más para deshacerme de él. Realmente no sé qué está mal, lo he probado en tres servidores locales diferentes y hay el mismo problema en cada uno de ellos. Si alguien tiene alguna idea o sugerencia, por favor, ayuda!

    
respondido por el jlub 08.09.2011 - 18:57
1

Cuando save_post se ejecuta, ya ha guardado la publicación en la base de datos.

Mirando el código del núcleo de WordPress, más específicamente en la función wp-includes/post.php ' update_post() , no hay una forma integrada de interceptar una solicitud antes de que se guarde en la base de datos.

Sin embargo, podemos enganchar pre_post_update y usar header() y get_post_edit_link() para evitar que la publicación se guarde.

<?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' );
    
respondido por el Lucas Bustamante 29.07.2018 - 23:54
0

He escrito un complemento que agrega un manejo de errores instantáneos para las pantallas de edición posterior y evita que las publicaciones se publiquen hasta que se completen los campos obligatorios:

enlace

Le permite hacer que los campos de publicación sean obligatorios, pero puede usar la API que proporciona para hacer que los campos personalizados sean necesarios también con un mensaje de error personalizable y una función de validación. De manera predeterminada, se comprueba si el campo está vacío o no.

    
respondido por el sanchothefat 19.11.2012 - 11:00

Lea otras preguntas en las etiquetas