I have a post type the uses post_save to take the address from the post-meta and retrieve the lat/lng coordinates from the Google API. I need a way of notifying the user if there was an issue with retrieving the coordintes. I tried using admin_notices, but nothing displayed:

public static function update_notice() {
  echo "<div class='error'><p>Failed to retrieve coordinates. Please check key and address.<p></div>";
  remove_action('admin_notices', 'update_notice');
}

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

I'm not sure if I'm using it incorrectly or in the wrong context. To be clear, in the actual code the add_action is in another function in the same class. That's working fine.

up vote 24 down vote accepted

The reason this doesn't work is because there is a redirection happening after the save_post action. One way you can acheive want you want is by implementing a quick work around using query vars.

Here is a sample class to demonstrate:

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 ) {
   // Do you stuff here
   // ...

   // Add your query var if the coordinates are not retreive correctly.
   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
  }
}

Hope this helps you a little bit. Cheers

  • Works great, thanks! But there's a missing closing bracket in the first line in the public function admin_notices() (an extra closing bracket in the if ( ! isset(.. line) – Rhys Wynne Jan 28 '15 at 16:04
  • I've added remove_query_arg('YOUR_QUERY_VAR'); as i found it can be set from the last update. – Tony O'Hagan Jul 6 at 8:12
  • +1 Good answer. – Mark Aug 7 at 7:35

Made a wrapper class for this kind of scenario. Actually the class can be used in any scenario involving displaying notices. I use the PSR standards, so the naming is atypical of Wordpress code.

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

Usage:

add_action('admin_notices', [new AdminNotice(), 'displayAdminNotice']);
AdminNotice::displayError(__('An error occurred, check logs.'));

The notice is displayed once.

In addition to @jonathanbardo's answer which is great and functions well, if you want to remove the query argument after the new page is loaded, you can use the removable_query_args filter. You get an array of argument names to which you can append your own argument. Then WP will take care of removing all of the arguments in the list from the 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;
}

Something like:

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

Will become:

'...post.php?post=1'

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.