Cum să adaugi o notificare admin la salvarea/actualizarea unui articol
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.

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!

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(..
)

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

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ă.

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'

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

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?

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'.

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