Mengirim pesan kesalahan / peringatan dari kotak meta ke “admin_notices”

20

Saya memiliki kotak meta sederhana yang memperbarui bidang khusus pos (menggunakan update_post_meta()).

Bagaimana saya bisa mengirim pesan kesalahan atau peringatan ke halaman berikutnya setelah pengguna menerbitkan / memperbarui posting dan tidak mengisi salah satu bidang kotak meta (atau mengisinya dengan data yang tidak valid)?

onetrickpony
sumber

Jawaban:

9

Anda dapat melakukan ini dengan tangan, tetapi WP biasanya melakukannya seperti ini untuk kesalahan pengaturan:

  1. add_settings_error() untuk membuat pesan.
  2. Kemudian set_transient('settings_errors', get_settings_errors(), 30);
  3. settings_errors()di admin_noticeskait untuk ditampilkan (perlu kait untuk layar non-pengaturan).
Jarang
sumber
ia melakukan apa yang saya inginkan, tetapi tidakkah ini mengisi database dengan banyak transien?
onetrickpony
@One Trick Pony dalam transient proses asli dihapus secara eksplisit (lihat get_settings_errors()sumber). Anda mungkin perlu melakukannya sendiri jika mengadaptasi logika untuk halaman non-pengaturan.
Paling lambat
2
masih saya tidak suka ide menyimpan pesan kesalahan sementara di db. Saya akan menggunakan ajax untuk memperingatkan pengguna tentang perubahan input
onetrickpony
Dengan caching objek, kekacauan basis data tidak akan menjadi masalah.
lkraav
15

Anda bisa menggunakan admin_noticespengait

pertama-tama tentukan fungsi pemberitahuan:

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

Anda yang Anda gunakan untuk menyimpan fungsi berdasarkan jika perlu tambahkan:

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

Memperbarui

Seperti yang saya janjikan di sini adalah contoh dari bagaimana saya menambahkan pesan kesalahan dari metabox saya

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

}

Sekarang ketika mencari kode ini saya menemukan cara lama saya melakukannya menggunakan post_updated_messageshook filter di tentang cara yang sama jadi saya akan menambahkannya juga:

<?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
sumber
tidak benar-benar berfungsi karena setelah Anda menyimpan posting, Anda diarahkan agar tindakan tidak pernah berjalan ...
onetrickpony
1
Diarahkan ke mana? Dan kode di atas adalah apa yang saya gunakan jadi saya tahu itu berfungsi.
Bainternet
Apakah fungsi penyimpanan metabox Anda terhubung save_post?
onetrickpony
1
terima kasih, tetapi ini melakukan hal yang sama seperti yang ditunjukkan Rarst: pesan kesalahan disimpan dalam db, dan kemudian diambil dan dihapus pada halaman berikutnya.
onetrickpony
1
-1 untuk menggunakan DB. Anda tidak dapat menjamin pengguna yang benar akan melihat kesalahan. Juga, tidak layak overhead yang tidak perlu. Karena tidak memiliki cara yang jelas untuk menangani kesalahan metabox, ini adalah pekerjaan yang baik tetapi masih belum efisien. Saya menambahkan contoh cara saya melakukan ini dalam jawaban baru untuk membantu orang lain.
Jeremy
11

Jawaban ini [ mirror ] dari Otto di WP Tavern, sebenarnya memecahkan masalah sementara dengan melakukan apa yang dilakukan WordPress sendiri untuk mengatasi masalah pengalihan. Benar-benar bekerja untuk saya.

Masalahnya adalah transien ada untuk semua orang. Jika Anda memiliki lebih dari satu pengguna melakukan hal-hal pada saat yang sama, pesan kesalahan dapat pergi ke orang yang salah. Ini kondisi balapan.

WordPress sebenarnya melakukan ini dengan mengirimkan parameter pesan di URL. Nomor pesan menunjukkan pesan mana yang akan ditampilkan.

Anda dapat melakukan hal yang sama dengan mengaitkan redirect_post_locationfilter dan kemudian menggunakan add_query_arguntuk menambahkan parameter Anda sendiri ke permintaan. Seperti itu:

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

Ini menambah my_message=123kueri. Kemudian, setelah pengalihan, Anda dapat mendeteksi pengaturan my_message di $_GETdan menampilkan pesan yang sesuai.

Ana Ban
sumber
3

Saya tahu pertanyaan ini sudah lama tetapi saya menemukan jawabannya di sini untuk tidak menyelesaikan masalah.

Memperluas jawaban dari Ana Ban, menggunakan metode Otto , saya menemukan ini menjadi metode terbaik untuk menangani kesalahan. Ini tidak perlu menyimpan kesalahan di db.

Saya menyertakan versi stripped down dari objek Metabox yang saya gunakan. Ini memungkinkan saya untuk dengan mudah menambahkan pesan kesalahan baru dan memastikan pengguna yang benar melihat pesan kesalahan (menggunakan db, ini bukan jaminan).

<?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
sumber
Satu-satunya masalah yang saya miliki dengan jawaban ini adalah tidak bekerja dengan PHP 5.2. Saya tidak mengatakan kita semua harus mendukung HPP 5.2, tetapi sampai WordPress memiliki PHP 5.2 sebagai persyaratan minimum, kita perlu mendukungnya jika kita mendistribusikan plugin :(
Sudar
1
Jika Anda menghapus fungsi anonim dan menjadikannya metode publik, itu akan berfungsi dengan baik. Saya memahami masalah Anda, tetapi secara pribadi saya tidak akan mengembangkan untuk versi PHP EOL ( php.net/eol.php ) 5.2 EOL adalah 6 Januari 2011. WordPress seharusnya membuat lebih banyak upaya untuk tidak mendukung versi EOL tapi itu cerita lain ditambah banyak perusahaan hosting yang buruk yang masih menyediakan versi EOL ...
Jeremy