[wp-hackers] Settings API: Showing errors if validation fails
Ade Walker
photofantaisie at gmail.com
Thu Dec 17 07:18:56 UTC 2009
Jeremy,
I ran across exactly the same problem you describe with one of my
plugins<http://wordpress.org/extend/plugins/dynamic-content-gallery-plugin/>.
In fact, just adding a simple Reset Settings option on the Settings page
became problematic in order to get a "You have reset the settings" message
to work. You're right, the problem is the page redirect which means the
usual old methods of doing this don't work.
I ended up using two functions: the register_settings callback function just
to sanitise the user input and a separate validation function to recheck
what's been entered and generate error messages if necessary. The validation
function is called each time the Settings page is loaded. As for the Reset
message, I have ended up with a rather clunky (or so it seems to me) method,
which involves a hidden option called "just-reset". This is captured in the
$input array and, if "true", $input is replaced with the default settings,
and $input['just-reset'] is set to true (all options are kept in one array,
which is the reason for this), and then the $input array is returned. I then
have another function hooked to admin_notices which checks if the
$options['just-reset'] is true and, if so, prints out a "You've reset your
settings to default" message, then changes $options['just-reset'] to false,
and then runs update_option. It's probably easier to follow me if you look
at the source code of the plugin in question, :-/
My clunky approach works and, since the Settings page is rarely touched once
the plugin has been initially set-up, I'm not too worried about the extra
code that all of this involves. Having said that, there should be an easier
way. Perhaps there is, and I've missed it?
Certainly, I agree, there should be an easier way to do something more with
the output of the register_settings callback function.
Hope this helps.
Ade.
2009/12/17 Jeremy Clarke <jer at simianuprising.com>
> After the recent discussion about the Settings API and before I added a
> bunch of settings to my custom plugin I decided to follow Otto's tutorial
> and set up my options page using registered settings, settings sections and
> settings fields. (
> http://ottodestruct.com/blog/2009/wordpress-settings-api-tutorial/)
>
> It took a while but I got it all working and overall I'm really happy with
> how the system works and cleans up my incredibly messy code.
>
> That said I can't find any way to show users errors when they give invalid
> input.
>
> When you register_setting() your setting (which is probably an array of
> options, you run register_settings() once for each wp_options entry), you
> give it a validation callback function.
>
> This function gives you $input which is the $_POST value for your option
> and
> you return the value you want saved to the db. It actually runs as a filter
> during update_option(), which is what gets run on all the Settings API
> stuff
> when you save the page. The idea is you filter/sanitize etc the data in the
> function and only return what is good.
>
> This works great if what you want to do is either a) return correct input
> or
> b) return absolutely nothing, but leaves you stranded if you want to help
> your users correct their mistake. In fact no matter what happens with the
> validation the user sees "Settings Saved" at the top of the screen after
> submitting a form. This is super bad usability and could easily lead to
> lots
> of users thinking their data was saved when in fact it wasn't.
>
> As a perfect example of the defect try changing the admin email setting in
> a
> WP install to something without an @ sign (a validation error). The result
> is 'Settings Saved' at the top and an empty admin email field. Needless to
> say, this is a nightmare for so many reasons.
>
>
> So my question: Has anyone found a way around this issue on their own? As
> far as I can tell there is no built in way to handle it, but maybe someone
> has a hack we can use till it gets solved in core? Preferably something
> that
> takes less code than going back to not using the Settings API?
>
> Part of the problem is that the processing and validation happen on a
> different execution from the pageload the user ends up on, during the load
> of /wp-admin/options.php, which is what you target your <form> at when
> using
> the Settings API. Once the Settings API has finished its saving/validation
> it does this:
>
> $goback = add_query_arg( 'updated', 'true', wp_get_referer() );
> wp_redirect( $goback );
>
> So there is pretty much no way to send back data about the validation
> error.
>
> In #wordpress-dev Mark Jaquith recommended doing
>
> wp_redirect( $your_plugin_admin_url . '&mypluginerrorid=1' );
> exit();
>
> when there is a validation error. But that would mean giving up on any
> other
> values in the same registered setting (none of it would be saved), as well
> as any other setting sections/fields that hadn't been processed yet during
> that form submission.
>
> Any ideas?
>
> In terms of building out core to take care of it I think the solution is a
> function that can be called during an options validation that saves a value
> which gets added to the wp_redirect() before it gets sent back. I.e. in
> options.php instead of just adding 'updated', 'true' it would first check
> for an alternate message and use that instead. Something like:
>
> add_settings_error("Sorry, what you entered for Admin Email is
> definitely not an email. Maybe an @ would be nice?");
>
> Then something like get_settings_error() to fill the add_query_var() before
> redirection.
>
> You could also create a $error_msg variable in your validation function and
> just add new text to it as you go along validating different values. This
> way you could also put good news in there like "Email saved, subscription
> preferences saved" etc.
>
> Without any error messaging about validation the Settings API is pretty
> crippled, almost to the point of being useless compared to processing the
> values yourself. Hopefully I'm just missing something obvious and Otto can
> yell at me for writing such a long email for nothing :)
>
> Wishing I'd kicked the tires more when this first came out,
>
> --
> Jeremy Clarke | http://jeremyclarke.org
> Code and Design | http://globalvoicesonline.org
> _______________________________________________
> wp-hackers mailing list
> wp-hackers at lists.automattic.com
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>
More information about the wp-hackers
mailing list