web-dev-qa-db-fra.com

Ajouter la validation et la gestion des erreurs lors de la sauvegarde des champs personnalisés?

J'ai une fonction qui définit un champ personnalisé sur un type de publication. Dites que le champ est "subhead".

Une fois la publication sauvegardée, je souhaite valider une entrée et afficher un message d'erreur sur l'écran d'édition si nécessaire. Quelque chose comme:

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

J'essaie de lier ceci à l'action save_post, mais je n'arrive pas à comprendre comment gérer les erreurs. Il ne semble pas qu'un objet d'erreur ait été passé dans la fonction, et si je crée mon propre obj WP_Error et le retourne, il n'est pas respecté par le mécanisme qui génère des erreurs sur la page d'édition.

J'ai actuellement un message d'erreur sur la page dans ma méta-boîte personnalisée, mais ce n'est pas l'idéal - je préfère avoir une grosse erreur rouge comme le haut, comme WP normalement affiche.

Des idées?

METTRE À JOUR:

Sur la base de la réponse de @Denis, j'ai essayé différentes choses. L'enregistrement des erreurs en tant que global n'a pas fonctionné, car Wordpress effectue une redirection pendant le processus save_post, ce qui élimine le global avant que vous puissiez l'afficher.

J'ai fini par les stocker dans un méta-champ. Le problème avec ceci est que vous devez les effacer, sinon ils ne disparaîtront pas lorsque vous naviguerez sur une autre page. J'ai donc dû ajouter une autre fonction attachée à admin_footer qui efface les erreurs.

Je ne m'attendais pas à ce que la gestion des erreurs pour quelque chose d'aussi courant (mettre à jour les messages) soit aussi maladroite. Est-ce que je manque quelque chose d'évident ou est-ce la meilleure approche?

// 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' );
29
MathSmath

Stockez les erreurs dans votre classe ou globalement, éventuellement dans une méta et un transitoire, et affichez-les dans les notifications de l'administrateur sur les requêtes POST. WP ne comporte aucun gestionnaire de messages flash.

7
Denis de Bernardy

Je suggère d’utiliser des sessions car cela ne créera pas d’effets étranges lorsque deux utilisateurs s’éditeront en même temps. Alors voici ce que je fais:

Les sessions ne sont pas lancées par WordPress. Vous devez donc démarrer une session dans votre plugin, functions.php ou même wp-config.php:

if (!session_id())
  session_start();

Lorsque vous enregistrez le message, ajoutez des erreurs et des avis à la session:

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

Imprimez les avis et les erreurs, puis nettoyez les messages de la session:

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

Basé sur pospi s suggestion utiliser transitoires , je suis arrivé avec ce qui suit. Le seul problème est qu'il n'y a pas de crochet pour mettre le message en dessous du h2 où vont les autres messages, donc je devais faire un bidouillage jQuery pour le faire arriver.

Tout d’abord, enregistrez le message d’erreur dans votre gestionnaire save_post (ou similaire). Je lui donne une courte durée de vie de 60 secondes, il est donc suffisamment long pour que la redirection se produise.

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

Ensuite, récupérez simplement ce message d’erreur lors du chargement de la page suivante et affichez-le. Je le supprime aussi pour qu'il ne soit pas affiché deux fois.

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

Étant donné que admin_notices se déclenche avant que le contenu de la page principale ne soit généré, la notification n'indique pas où vont les autres messages post-édition. Je devais donc utiliser ce jQuery pour le déplacer là:

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

Étant donné que l'ID de publication fait partie du nom transitoire, cela devrait fonctionner dans la plupart des environnements multi-utilisateurs, sauf lorsque plusieurs utilisateurs modifient simultanément la même publication.

5
Joshua Coady

Lorsque save_post est exécuté, la publication a déjà été enregistrée dans la base de données.

En examinant le code principal de WordPress, plus particulièrement la fonction update_post() du wp-includes/post.php, il n’existe aucun moyen intégré d’intercepter une demande avant son enregistrement dans la base de données.

Cependant, nous pouvons accrocher pre_post_update et utiliser header() et get_post_edit_link() pour empêcher la publication de la publication.

<?php

/**
*   Performs validation before saving/inserting custom post type
*/
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'] == 'my_custom_post_type') {
        // Deny post titles with less than 5 characters
        if (strlen($post_data['post_title'] < 5)) {
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

Si vous souhaitez informer l’utilisateur de ce qui ne va pas, consultez cette Gist: https://Gist.github.com/Luc45/09f2f9d0c0e574c0285051b288a0f935

2
Lucas Bustamante

Pourquoi ne validez-vous pas votre champ à l'aide de Javascript? Je pense que ce serait la meilleure approche pour cela.

1
Horttcore

En essayant d'utiliser le script ci-dessus, j'ai rencontré un problème étrange. Deux messages sont affichés sur l'écran d'édition après la mise à jour. L'un montre l'état du contenu de la sauvegarde précédente et un autre du courant. Par exemple, si je sauvegarde correctement le message et commets ensuite une erreur, le premier est "erreur" et le second est "ok" - bien qu'ils soient générés dans le même temps. Si je modifie le script et n’ajoute qu’un seul message (par exemple, "erreur"), lancez une mise à jour avec "erreur", puis une autre avec "ok", le message "erreur" reste (est affiché pour la deuxième fois). Je dois économiser avec "ok" encore une fois pour m'en débarrasser. Je ne sais vraiment pas ce qui ne va pas, je l'ai testé sur trois serveurs locaux différents et le même problème se pose pour chacun d'entre eux. Si quelqu'un a une idée ou une suggestion, aidez-nous!

1
jlub

J'ai écrit un plugin qui ajoute une gestion des erreurs flash pour les écrans de post-édition et empêche la publication de post tant que les champs requis ne sont pas renseignés:

https://github.com/interconnectit/required-fields

Il vous permet de rendre obligatoires les champs de publication, mais vous pouvez utiliser l'API fournie pour créer des champs personnalisés obligatoires avec un message d'erreur personnalisable et une fonction de validation. Il vérifie par défaut si le champ est vide ou non.

0
sanchothefat