Cum să adaugi o notificare admin la salvarea/actualizarea unui articol

27 iun. 2014, 19:37:51
Vizualizări: 31.3K
Voturi: 29

Am un tip de postare care folosește post_save pentru a prelua adresa din post-meta și a recupera coordonatele lat/lng de la API-ul Google. Am nevoie de o modalitate de a notifica utilizatorul dacă a apărut o problemă la preluarea coordonatelor. Am încercat să folosesc admin_notices, dar nu s-a afișat nimic:

public static function update_notice() {
  echo "<div class='error'><p>Nu s-au putut prelua coordonatele. Vă rugăm verificați cheia și adresa.<p></div>";
  remove_action('admin_notices', 'update_notice');
}

add_action('admin_notices', array('GeoPost', 'update_notice'));

Nu sunt sigur dacă îl folosesc incorect sau în contextul greșit. Pentru clarificare, în codul real funcția add_action se află în altă funcție din aceeași clasă. Acea parte funcționează bine.

1
Comentarii

Am dezvoltat un script care vă permite să adăugați cu ușurință notificări administrative care pot fi închise/sau statice https://github.com/askupasoftware/wp-admin-notification

Yoav Kadosh Yoav Kadosh
25 iul. 2016 17:51:29
Toate răspunsurile la întrebare 5
3
42

Motivul pentru care acest lucru nu funcționează este pentru că există o redirecționare care are loc după acțiunea save_post. O modalitate prin care poți obține ceea ce dorești este prin implementarea unei soluții rapide folosind variabile de interogare (query vars).

Iată o clasă demonstrativă:

class My_Awesome_Plugin {
  public function __construct(){
   add_action( 'save_post', array( $this, 'save_post' ) );
   add_action( 'admin_notices', array( $this, 'admin_notices' ) );
  }

  public function save_post( $post_id, $post, $update ) {
   // Execută operațiunile tale aici
   // ...

   // Adaugă variabila de interogare dacă coordonatele nu sunt preluate corect
   add_filter( 'redirect_post_location', array( $this, 'add_notice_query_var' ), 99 );
  }

  public function add_notice_query_var( $location ) {
   remove_filter( 'redirect_post_location', array( $this, 'add_notice_query_var' ), 99 );
   return add_query_arg( array( 'YOUR_QUERY_VAR' => 'ID' ), $location );
  }

  public function admin_notices() {
   if ( ! isset( $_GET['YOUR_QUERY_VAR'] ) ) {
     return;
   }
   ?>
   <div class="updated">
      <p><?php esc_html_e( 'YOUR MESSAGE', 'text-domain' ); ?></p>
   </div>
   <?php
  }
}

Sper că acest lucru te ajută puțin. Noroc!

27 iun. 2014 22:47:34
Comentarii

Funcționează excelent, mulțumesc! Dar lipsește o paranteză de închidere în prima linie din public function admin_notices() (o paranteză de închidere în plus în linia if ( ! isset(..)

Rhys Wynne Rhys Wynne
28 ian. 2015 18:04:12

Am adăugat remove_query_arg('YOUR_QUERY_VAR'); deoarece am observat că poate fi setat din ultima actualizare.

Tony O'Hagan Tony O'Hagan
6 iul. 2018 11:12:29

+1 Răspuns bun.

Mark Mark
7 aug. 2018 10:35:53
1
15

Am creat o clasă wrapper pentru acest tip de scenariu. De fapt, clasa poate fi folosită în orice scenariu care implică afișarea de notificări. Folosesc standardele PSR, deci denumirile sunt atipice pentru codul WordPress.

class AdminNotice
{
    const NOTICE_FIELD = 'my_admin_notice_message';

    public function displayAdminNotice()
    {
        $option      = get_option(self::NOTICE_FIELD);
        $message     = isset($option['message']) ? $option['message'] : false;
        $noticeLevel = ! empty($option['notice-level']) ? $option['notice-level'] : 'notice-error';

        if ($message) {
            echo "<div class='notice {$noticeLevel} is-dismissible'><p>{$message}</p></div>";
            delete_option(self::NOTICE_FIELD);
        }
    }

    public static function displayError($message)
    {
        self::updateOption($message, 'notice-error');
    }

    public static function displayWarning($message)
    {
        self::updateOption($message, 'notice-warning');
    }

    public static function displayInfo($message)
    {
        self::updateOption($message, 'notice-info');
    }

    public static function displaySuccess($message)
    {
        self::updateOption($message, 'notice-success');
    }

    protected static function updateOption($message, $noticeLevel) {
        update_option(self::NOTICE_FIELD, [
            'message' => $message,
            'notice-level' => $noticeLevel
        ]);
    }
}

Utilizare:

add_action('admin_notices', [new AdminNotice(), 'displayAdminNotice']);
AdminNotice::displayError(__('A apărut o eroare, verifică jurnalele.'));

Notificarea este afișată o singură dată.

29 mar. 2016 20:01:13
Comentarii

Mulțumesc, funcționează perfect!

JorensM JorensM
10 mar. 2023 11:54:00
0

Pe lângă răspunsul lui @jonathanbardo, care este excelent și funcționează bine, dacă doriți să eliminați argumentul query după ce noua pagină este încărcată, puteți utiliza filtrul removable_query_args. Veți primi un array cu nume de argumente la care puteți adăuga propriul argument. Apoi WordPress se va ocupa de eliminarea tuturor argumentelor din listă din URL.

public function __construct() {
    ...
    add_filter('removable_query_args', array($this, 'add_removable_arg'));
}

public function add_removable_arg($args) {
    array_push($args, 'my-query-arg');
    return $args;
}

Ceva de genul:

'...post.php?post=1&my-query-arg=10'

Va deveni:

'...post.php?post=1'
20 mar. 2017 23:20:23
2

Simplu, elegant, bazat pe get_settings_errors().

function wpse152033_set_admin_notice($id, $message, $status = 'success') {
    set_transient('wpse152033' . '_' . $id, [
        'message' => $message,
        'status' => $status
    ], 30);
}

function wpse152033_get_admin_notice($id) {
    $transient = get_transient( 'wpse152033' . '_' . $id );
    if ( isset( $_GET['settings-updated'] ) && $_GET['settings-updated'] && $transient ) {
        delete_transient( 'wpse152033' . '_' . $id );
    }
    return $transient;
}

Utilizare

În handler-ul tău de cerere POST:

wpse152033_set_admin_notice(get_current_user_id(), 'Salut lume', 'error');
wp_redirect(add_query_arg('settings-updated', 'true',  wp_get_referer()));

Acolo unde dorești să afișezi notificarea administrativă, de obicei în hook-ul admin_notices.

$notice = $this->get_admin_notice(get_current_user_id());
if (!empty($notice) && is_array($notice)) {
    $status = array_key_exists('status', $notice) ? $notice['status'] : 'success';
    $message = array_key_exists('message', $notice) ? $notice['message'] : '';
    print '<div class="notice notice-'.$status.' is-dismissible">'.$message.'</div>';
}
9 ian. 2019 10:37:36
Comentarii

Aceasta este o implementare foarte frumoasă, felicitări, domnule. Ar avea sens să renunțăm la linia wp_redirect... și să adăugăm pur și simplu un al 3-lea element în array-ul transient folosind un nonce pentru o securitate suplimentară? Transientul nu va returna nimic dacă nu este setat, ceea ce ar fi suficient pentru a ieși din instrucțiunea if din get_admin_notice, nu-i așa?

csaborio csaborio
23 mai 2021 06:58:47

Am creat acest gist în caz că ajută pe cineva: https://gist.github.com/csaborio001/d5a8fa84fba3ff4ff22d43f64179feba Pentru a folosi, pur și simplu AdminNotice::display_admin_message( 'mesaj', 'status'), și va trebui să conectați process_messages cu hook-ul 'admin_notices'.

csaborio csaborio
23 mai 2021 07:20:30
0

Puteți realiza acest lucru făcând o redirecționare și transmitând argumente de interogare prin filtrul redirect_post_location. Există și redirect_term_location care va funcționa pentru taxonomii/termeni.

Mai întâi adăugați acțiunea admin_notices care va fi întotdeauna activă, dar va afișa notificarea doar în anumite condiții.

add_action( 'admin_notices', 'general_admin_notice' );

function general_admin_notice(){
  global $pagenow;

  if ( 'post.php' === $pagenow && isset($_GET['post']) && 'custom_post_type' === get_post_type( $_GET['post'] ) ){

    if ( isset($_GET['empty'])) {
      
      // Transformă șirul în array pentru a putea parcurge termenii
      $terms_id = explode( ',', $_GET['empty'] );

      echo '<div class="notice notice-error is-dismissible">
                <p>';
                foreach ( $terms_id as $term_id ) {
                  $term = get_term( $term_id, 'custom_taxonomy' );
                  echo '<a href="'.get_term_link( $term ).'">'.$term->name.'</a>, ';
                }
              echo 'nutrienții sunt goi.</p>
            </div>';
      }
    }
}

Apoi trebuie să redirecționați pagina după salvare și să transmiteți un argument de interogare cu add_query_arg. Modul în care am făcut eu aici permite un input dinamic care este afișat în notificarea de admin.

        if ( !empty($empty_error) ) {
            add_filter('redirect_post_location', function($loc) use ($empty_error) {
                trigger_error( $empty_error);
                return add_query_arg( 'empty', implode(',', $empty_error), $loc );
            }); 
        }

În cazul meu, fac un array_push pe variabila $empty_error cu un ID de termen. Notificarea de admin va afișa apoi toți termenii care au o eroare, cu un link către fiecare termen.

Puteți folosi și removable_query_args pentru a elimina argumentele de interogare adăugate, astfel încât URL-ul să arate mai curat. Notificarea de admin va dispărea dacă reîmprospătați pagina.

add_filter('removable_query_args', 'add_removable_arg');

function add_removable_arg($args) {
    array_push($args, 'empty');
    return $args;
}
16 apr. 2021 16:29:44