Come aggiungere una notifica di amministrazione al salvataggio/aggiornamento di un post
Ho un tipo di post che utilizza post_save per prendere l'indirizzo dai post-meta e recuperare le coordinate lat/lng dall'API di Google. Ho bisogno di un modo per notificare all'utente se ci sono stati problemi nel recupero delle coordinate. Ho provato a usare admin_notices, ma non viene visualizzato nulla:
public static function update_notice() {
echo "<div class='error'><p>Impossibile recuperare le coordinate. Controlla la chiave e l'indirizzo.<p></div>";
remove_action('admin_notices', 'update_notice');
}
add_action('admin_notices', array('GeoPost', 'update_notice'));
Non sono sicuro se lo sto usando in modo errato o nel contesto sbagliato. Per essere chiaro, nel codice effettivo l'add_action si trova in un'altra funzione nella stessa classe. Quella parte funziona correttamente.

Il motivo per cui questo non funziona è perché avviene un reindirizzamento dopo l'azione save_post. Un modo per ottenere ciò che vuoi è implementare una soluzione alternativa utilizzando le query vars.
Ecco una classe di esempio per dimostrarlo:
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 ) {
// Fai quello che devi fare qui
// ...
// Aggiungi la tua query var se le coordinate non vengono recuperate correttamente.
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( 'IL TUO MESSAGGIO', 'text-domain' ); ?></p>
</div>
<?php
}
}
Spero che questo ti sia d'aiuto. Saluti

Funziona perfettamente, grazie! Ma c'è una parentesi di chiusura mancante nella prima riga della public function admin_notices()
(una parentesi di chiusura extra nella riga if ( ! isset(..
)

Ho aggiunto remove_query_arg('YOUR_QUERY_VAR');
poiché ho scoperto che può essere impostato dall'ultimo aggiornamento.

Ho creato una classe wrapper per questo tipo di scenario. In realtà la classe può essere utilizzata in qualsiasi scenario che coinvolga la visualizzazione di notifiche. Utilizzo gli standard PSR, quindi la denominazione non è tipica del codice 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
]);
}
}
Utilizzo:
add_action('admin_notices', [new AdminNotice(), 'displayAdminNotice']);
AdminNotice::displayError(__('Si è verificato un errore, controlla i log.'));
La notifica viene visualizzata una sola volta.

Oltre alla risposta di @jonathanbardo, che è ottima e funziona bene, se vuoi rimuovere l'argomento della query dopo che la nuova pagina è stata caricata, puoi usare il filtro removable_query_args. Ricevi un array di nomi di argomenti a cui puoi aggiungere il tuo. Quindi WordPress si occuperà di rimuovere tutti gli argomenti nella lista dall'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;
}
Qualcosa come:
'...post.php?post=1&my-query-arg=10'
Diventerà:
'...post.php?post=1'

Semplice, elegante, basato su 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;
}
Utilizzo
Nel gestore della richiesta POST:
wpse152033_set_admin_notice(get_current_user_id(), 'Ciao mondo', 'error');
wp_redirect(add_query_arg('settings-updated', 'true', wp_get_referer()));
Dove vuoi utilizzare l'avviso di amministrazione, solitamente nell'hook 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>';
}

Questa è un'implementazione molto carina, complimenti a te, gentile signore. Avrebbe senso rimuovere la riga wp_redirect... e semplicemente aggiungere un terzo elemento all'array del transient usando un nonce per aumentare la sicurezza? Il transient non restituirà nulla se non è impostato, il che sarebbe sufficiente per uscire dall'istruzione if in get_admin_notice, no?

Ho creato questo gist nel caso possa aiutare qualcuno: https://gist.github.com/csaborio001/d5a8fa84fba3ff4ff22d43f64179feba Per usarlo, basta AdminNotice::display_admin_message( 'messaggio', 'stato'), e dovrai collegare process_messages con l'hook 'admin_notices'.

Puoi ottenere questo effettuando un reindirizzamento e passando gli argomenti della query con il filtro redirect_post_location
. Esiste anche redirect_term_location
che funziona per tassonomie/termini.
Per prima cosa aggiungi l'azione admin_notices
che sarà sempre attiva, ma mostrerà l'avviso solo in determinate condizioni.
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'])) {
// Converti la stringa in array, così possiamo ciclarla.
$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 'i nutrienti sono vuoti.</p>
</div>';
}
}
}
Poi devi reindirizzare la pagina dopo il salvataggio e passare un argomento della query con add_query_arg
. Nel modo in cui l'ho fatto qui puoi avere un input dinamico che viene mostrato nell'avviso di amministrazione.
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 );
});
}
Nel mio caso faccio un array_push
sulla variabile $empty_error
con un ID di termine. L'avviso di amministrazione mostrerà quindi tutti i termini che hanno un errore con un link al rispettivo termine.
Puoi anche usare removable_query_args
per rimuovere gli argomenti aggiunti, così l'URL appare più pulito. L'avviso di amministrazione scomparirà se ricarichi la pagina.
add_filter('removable_query_args', 'add_removable_arg');
function add_removable_arg($args) {
array_push($args, 'empty');
return $args;
}
