Übergeben von Fehler- / Warnmeldungen aus einer Meta-Box an "admin_notices"

20

Ich habe eine einfache Meta-Box, die die benutzerdefinierten Felder des Beitrags aktualisiert (mithilfe von update_post_meta()).

Wie kann ich eine Fehler- oder Warnmeldung an die nächste Seite senden, nachdem der Benutzer den Beitrag veröffentlicht / aktualisiert hat und eines der Meta-Box-Felder nicht ausgefüllt (oder mit ungültigen Daten gefüllt) hat?

ein Trickpony
quelle

Antworten:

9

Sie können dies von Hand tun, aber WP macht es bei Einstellungsfehlern von Haus aus so:

  1. add_settings_error() Nachricht erstellen.
  2. Dann set_transient('settings_errors', get_settings_errors(), 30);
  3. settings_errors()in admin_noticeshook zum Anzeigen (muss bei nicht eingestellten Bildschirmen angehängt werden).
Rarst
quelle
es macht was ich will, aber würde dies nicht die Datenbank mit Tonnen von Transienten füllen?
Onetrickpony
@One Trick Pony wird im native Process Transient explizit gelöscht (siehe get_settings_errors()Quelle). Möglicherweise müssen Sie dies selbst tun, wenn Sie die Logik für Nicht-Einstellungsseiten anpassen.
Rarst
2
trotzdem mag ich die idee nicht, temporäre fehlermeldungen in der db zu speichern. Ich werde
Ajax
Mit dem Objekt-Caching wäre Datenbank-Unordnung kein Problem.
lkraav
15

Sie können admin_noticesHaken verwenden

Definieren Sie zuerst die Benachrichtigungsfunktion:

function my_admin_notice(){
    //print the message
    echo '<div id="message">
       <p>metabox as errors on save message here!!!</p>
    </div>';
    //make sure to remove notice after its displayed so its only displayed when needed.
    remove_action('admin_notices', 'my_admin_notice');
}

Die Funktion, auf der Sie Ihre Metabox speichern, fügt bei Bedarf Folgendes hinzu:

...
...
if($errors){
    add_action('admin_notices', 'my_admin_notice');
}
...
...

Aktualisieren

Wie ich hier versprochen habe, ist ein Beispiel dafür, wie ich eine Fehlermeldung aus meiner Metabox hinzufüge

<?php
/*
Plugin Name: one-trick-pony-notice
Plugin URI: http://en.bainternet.info
Description: Just to proof a point using admin notice form metabox
Version: 1.0
Author: Bainternet
Author URI: http://en.bainternet.info
*/

/*  admin notice */
function my_admin_notice(){
    //print the message
    global $post;
    $notice = get_option('otp_notice');
    if (empty($notice)) return '';
    foreach($notice as $pid => $m){
        if ($post->ID == $pid ){
            echo '<div id="message" class="error"><p>'.$m.'</p></div>';
            //make sure to remove notice after its displayed so its only displayed when needed.
            unset($notice[$pid]);
            update_option('otp_notice',$notice);
            break;
        }
    }
}

//hooks

add_action('add_meta_boxes', 'OT_mt_add');
add_action('save_post', 'OT_mt_save');
add_action('admin_notices', 'my_admin_notice',0);

//add metabox
function OT_mt_add() {
    add_meta_box('OT_mt_sectionid', __( 'One Trick Meta Box notice', 'textdomain' ),'OT_mt_display','post');
}

//display metabox
function OT_mt_display() {

  // Use nonce for verification
  wp_nonce_field( plugin_basename(__FILE__), 'myplugin_noncename' );

  // The actual fields for data entry
  echo '<label for="myplugin_new_field">';
       _e("leave blank to get a notice on publish or update", 'textdomain' );
  echo '</label> ';
  echo '<input type="text" id="ot_field" name="ot_field" value="" size="25" />';

}


//save metabox here is were i check the fields and if empty i display a message
function OT_mt_save( $post_id ) {

  // verify this came from the our screen and with proper authorization,
  // because save_post can be triggered at other times
    if (!isset($_POST['myplugin_noncename'])) return $post_id;
  if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
      return $post_id;

  // verify if this is an auto save routine. 
  // If it is our form has not been submitted, so we dont want to do anything
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
      return $post_id;


  if(!isset($_POST['ot_field']) || empty($_POST['ot_field'])){
    //field left empty so we add a notice
    $notice = get_option('otp_notice');
    $notice[$post_id] = "You have left the field empty";
    update_option('otp_notice',$notice);
  }

}

Als ich nach diesem Code suchte, fand ich meine alte Methode, post_updated_messagesFilter Hook zu verwenden, in etwa auf die gleiche Weise, also füge ich das auch hinzu:

<?php
/*
Plugin Name: one-trick-pony-notice2
Plugin URI: http://en.bainternet.info
Description: just like the one above but this time using post_updated_messages hook
Version: 1.0
Author: Bainternet
Author URI: http://en.bainternet.info
*/

//hooks
add_filter('post_updated_messages','my_messages',0);
add_action('add_meta_boxes', 'OT_mt_add');
add_action('save_post', 'OT_mt_save');


//add metabox
function OT_mt_add() {
    add_meta_box('OT_mt_sectionid', __( 'One Trick Meta Box notice', 'textdomain' ),'OT_mt_display','post');
}

//display metabox
function OT_mt_display() {

  // Use nonce for verification
  wp_nonce_field( plugin_basename(__FILE__), 'myplugin_noncename' );

  // The actual fields for data entry
  echo '<label for="myplugin_new_field">';
       _e("leave blank to get a notice on publish or update", 'textdomain' );
  echo '</label> ';
  echo '<input type="text" id="ot_field" name="ot_field" value="" size="25" />';

}


//save metabox here is were i check the fields and if empty i display a message
function OT_mt_save( $post_id ) {

  // verify this came from the our screen and with proper authorization,
  // because save_post can be triggered at other times
    if (!isset($_POST['myplugin_noncename'])) return $post_id;
  if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
      return $post_id;

  // verify if this is an auto save routine. 
  // If it is our form has not been submitted, so we dont want to do anything
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
      return $post_id;


  if(!isset($_POST['ot_field']) || empty($_POST['ot_field'])){
    //field left empty so we add a notice
    $notice = get_option('otp_notice');
    $notice[$post_id] = "You have left the field empty";
    update_option('otp_notice',$notice);
  }

}

//messages filter
function my_messages($m){
    global $post;
    $notice = get_option('otp_notice');
    if (empty($notice)) return $m;
    foreach($notice as $pid => $mm){
        if ($post->ID == $pid ){
            foreach ($m['post'] as $i => $message){
                $m['post'][$i] = $message.'<p>'.$mm.'</p>';

            }
            unset($notice[$pid]);
            update_option('otp_notice',$notice);
            break;
        }
    }
    return $m;
}
Bainternet
quelle
funktioniert nicht wirklich, da Sie nach dem Speichern des Beitrags umgeleitet werden, sodass keine Aktion ausgeführt wird ...
onetrickpony
1
Umgeleitet wo? Und der obige Code ist, was ich benutze, damit ich weiß, dass es funktioniert.
Bainternet
Ist Ihre Metabox-Speicherfunktion aktiviert save_post?
Onetrickpony
1
danke, aber das macht dasselbe wie Rarst: die fehlermeldung wird in der db gespeichert und dann auf der nächsten seite abgerufen und gelöscht.
Onetrickpony
1
-1 für die Verwendung eines DB. Sie können nicht garantieren, dass der richtige Benutzer den Fehler sieht. Auch den unnötigen Aufwand nicht wert. Wenn Sie keinen klaren Weg haben, um mit Metabox-Fehlern umzugehen, ist dies eine gute Arbeit, aber immer noch nicht effizient. Ich habe in einer neuen Antwort ein Beispiel hinzugefügt, wie ich das mache, um anderen zu helfen.
Jeremy
11

Diese Antwort [ Spiegel ] von Otto in WP Tavern löst das vorübergehende Problem tatsächlich, indem es das tut, was WordPress selbst tut, um das Umleitungsproblem zu überwinden. Total für mich gearbeitet.

Das Problem ist, dass Transienten für alle da sind. Wenn mehrere Benutzer gleichzeitig aktiv sind, kann die Fehlermeldung an die falsche Person gesendet werden. Es ist eine Rennbedingung.

WordPress tut dies tatsächlich durch Übergabe eines Nachrichtenparameters in der URL. Die Nachrichtennummer gibt an, welche Nachricht angezeigt werden soll.

Sie können dasselbe tun, indem Sie den redirect_post_locationFilter einhaken und dann verwenden add_query_arg, um der Anforderung Ihren eigenen Parameter hinzuzufügen. Wie so:

add_filter('redirect_post_location','my_message');
function my_message($loc) {
 return add_query_arg( 'my_message', 123, $loc );
}

Dies fügt my_message=123der Abfrage hinzu. Nach der Umleitung können Sie dann die Einstellung my_message in erkennen $_GETund die entsprechende Nachricht anzeigen.

Ana Ban
quelle
3

Ich weiß, dass diese Frage alt ist, aber ich finde hier die Antworten, um das Problem nicht zu lösen.

Nachdem ich die Antwort von Ana Ban mit Ottos Methode erweitert hatte , stellte ich fest, dass dies die beste Methode ist, um mit Fehlern umzugehen. Dies erfordert keine Speicherung der Fehler in der Datenbank.

Ich habe eine abgespeckte Version eines von mir verwendeten Metabox-Objekts hinzugefügt. Auf diese Weise kann ich auf einfache Weise neue Fehlermeldungen hinzufügen und sicherstellen, dass der richtige Benutzer die Fehlermeldung sieht (bei Verwendung der Datenbank ist dies keine Garantie).

<?php
/**
 * Class MetaboxExample
 */
class MetaboxExample {

    /**
     * Defines the whitelist for allowed screens (post_types)
     */
    private $_allowedScreens = array( 'SCREENS_TO_ALLOW_METABOX' );

    /**
     * Get parameter for the error box error code
     */
    const GET_METABOX_ERROR_PARAM = 'meta-error';

    /**
     * Defines admin hooks
     */
    public function __construct() {
        add_action('add_meta_boxes', array($this, 'addMetabox'), 50);
        add_action('save_post', array($this, 'saveMetabox'), 50);
        add_action('edit_form_top', array($this, 'adminNotices')); // NOTE: admin_notices doesn't position this right on custom post type pages, haven't testes this on POST or PAGE but I don't see this an issue
    }

    /**
     * Adds the metabox to specified post types
     */
    public function addMetabox() {
        foreach ( $this->_allowedScreens as $screen ) {
            add_meta_box(
                'PLUGIN_METABOX',
                __( 'TITLE', 'text_domain' ),
                array($this, 'metaBox'),
                $screen,
                'side',
                'high'
            );
        }
    }

    /**
     * Output metabox content
     * @param $post
     */
    public function metaBox($post) {
        // Add an nonce field so we can check for it later.
        wp_nonce_field( 'metaboxnonce', 'metaboxnonce' );
        // Load meta data for this metabox
        $someValue = get_post_meta( $post->ID, 'META_KEY_IDENTIFIER', true );
        ?>
        <p>
            <label for="some-value" style="width: 120px; display: inline-block;">
                <?php _e( 'Some Field:', 'text_domain' ); ?>
            </label>
            &nbsp;
            <input type="text" id="some-value" name="some_value" value="<?php esc_attr_e( $someValue ); ?>" size="25" />
        </p>
    <?php
    }

    /**
     * Save method for the metabox
     * @param $post_id
     */
    public function saveMetabox($post_id) {
        global $wpdb;

        // Check if our nonce is set.
        if ( ! isset( $_POST['metaboxnonce'] ) ) {
            return $post_id;
        }
        // Verify that the nonce is valid.
        if ( ! wp_verify_nonce( $_POST['metaboxnonce'], 'metaboxnonce' ) ) {
            return $post_id;
        }
        // If this is an autosave, our form has not been submitted, so we don't want to do anything.
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return $post_id;
        }
        // Check the user's permissions.
        if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) {
            if ( ! current_user_can( 'edit_page', $post_id ) ) {
                return $post_id;
            }
        } else {
            if ( ! current_user_can( 'edit_post', $post_id ) ) {
                return $post_id;
            }
        }
        // Make sure that it is set.
        if ( !isset( $_POST['some_value'] ) ) {
            return $post_id;
        }
        // Sanitize user input.
        $someValue = sanitize_text_field( $_POST['some_value'] );
        // Check to make sure there is a value
        if (empty($someValue)) {
            // Add our error code
            add_filter('redirect_post_location', function($loc) {
                return add_query_arg( self::GET_METABOX_ERROR_PARAM, 1, $loc );
            });
            return $post_id; // make sure to return so we don't allow further processing
        }
        // Update the meta field in the database.
        update_post_meta( $post_id, 'META_KEY_IDENTIFIER', $someValue );
    }

    /**
     * Metabox admin notices
     */
    public function adminNotices() {
        if (isset($_GET[self::GET_METABOX_ERROR_PARAM])) {
            $screen = get_current_screen();
            // Make sure we are in the proper post type
            if (in_array($screen->post_type, $this->_allowedScreens)) {
                $errorCode = (int) $_GET[self::GET_METABOX_ERROR_PARAM];
                switch($errorCode) {
                    case 1:
                        $this->_showAdminNotice( __('Some error happened', 'text_domain') );
                        break;
                    // More error codes go here for outputting errors
                }
            }
        }
    }

    /**
     * Shows the admin notice for the metabox
     * @param $message
     * @param string $type
     */
    private function _showAdminNotice($message, $type='error') {
        ?>
        <div class="<?php esc_attr_e($type); ?> below-h2">
            <p><?php echo $message; ?></p>
        </div>
    <?php
    }

}
Jeremy
quelle
Das einzige Problem, das ich mit dieser Antwort habe, ist, dass es mit PHP 5.2 nicht funktioniert. Ich sage nicht, dass wir alle HPP 5.2 unterstützen sollten, aber bis WordPress PHP 5.2 als Mindestanforderung hat, müssen wir es unterstützen, wenn wir das Plugin verteilen :(
Sudar
1
Wenn Sie die anonyme Funktion entfernt und als öffentliche Methode festgelegt haben, sollte sie ordnungsgemäß funktionieren. Ich verstehe Ihr Problem, aber ich persönlich werde nicht für eine EOL-Version von PHP ( php.net/eol.php ) entwickeln. 5.2 EOL war der 6. Januar 2011. WordPress sollte sich mehr Mühe geben, EOL-Versionen nicht zu unterstützen, aber das ist eine andere Geschichte plus viele schlechte Hosting-Unternehmen, die noch EOL-Versionen zur Verfügung gestellt ...
Jeremy