Title sounds counter-intuitive but bear with me. 🙂

I have options page, made with Settings API. When user enters invalid data I want to display error notice with add_settings_error() call.

But! To determine that data is invalid I need to make an remote API call. That call relies on saved data. So I can’t do this in sanitization callback (which is recommended place to throw such notices) because my data is not saved yet.

Instead I had tried to hooking my check into admin_notices. It works fine most of the time except one (and most important) case – when settings are saved they are always followed by native Settings saved. notice and my custom notices are completely ignored for some reason.

So how do I throw that error notice even if WP thinks everything is fine?

Edit

More focused question – why exactly Settings saved. trumps any other notices?

PS I could try to make API call optionally take data as argument instead of reading it from saved option, but so far I think it will make arguments overly bulky.

2 s
2

Ok, I think I have an idea what is going on.

  1. The list of notices to display is retrieved by get_settings_errors() ( source ).

  2. This function reads notices from global $wp_settings_errors unless there is settings_errors transient set, which trumps global var.

  3. When settings are saved there is check for no setting errors and if so Settings saved. notice is generated. After that (in either case) errors are saved into settings_errors transient (I assume to preserve them on redirect) ( source ) .

Basically no matter what notices you generate in your code – they will be ignored when transient is set and it is always going to be set after saving settings.

As for me it would make sense to concatenate transient with global variable rather than making it exclusive or choice.

And I guess to display custom notices when transient is set I will need to mess with that transient, which is probably not worth the trouble.

Leave a Reply

Your email address will not be published. Required fields are marked *