Verify Submitted Form Values and Show Warning Messages with Setting API

I'm making a plugin administration page with the settings API. I'd like to know a way to display a warning message when the user submits an invalid value.

For example, with the below code, if the user sends an empty value for Option A, the first input field, I'd like to show a message that says it's invalid and please fill the form. And the other submitted option values should not be saved to the database but remain in the input fields with the message on the page.

?php
/*
Plugin Name: Demo Verification Notice with Settings API
Description: Learning how to warn invalid values when submitting the form and take back the user to the setting page without saving the options.
Author: Teno
*/

add_action('admin_init', 'settingsapi_init');
function settingsapi_init(){
    register_setting( 'settingsapi_optiongroupname', 'settingsapi_optionname');
    add_settings_section('plugin_main', 'Section 1', 'settingsapi_sectiondescription', 'settingsapi_pageslug');
    add_settings_field('plugin_text_string_a', 'Option A', 'settingsapi_setting_string_a', 'settingsapi_pageslug', 'plugin_main');
    add_settings_field('plugin_text_string_b', 'Option B', 'settingsapi_setting_string_b', 'settingsapi_pageslug', 'plugin_main');
}

function settingsapi_sectiondescription() {
    echo 'pThis is a section description./p';
}
function settingsapi_setting_string_a() {
    $options = get_option('settingsapi_optionname');
    echo "input id='plugin_text_string' name='settingsapi_optionname[option_a]' size='40' type='text' value='{$options['option_a']}' /"; 
} 
function settingsapi_setting_string_b() {
    $options = get_option('settingsapi_optionname');
    echo "input id='plugin_text_string' name='settingsapi_optionname[option_b]' size='40' type='text' value='{$options['option_b']}' /"; 
}
// admin menu
add_action('admin_menu', 'plugin_admin_add_page');
function plugin_admin_add_page() {
    add_options_page('Custom Plugin Page', 'Demo Settings API Menu for Verification', 'manage_options', 'settingsapi_pageslug', 'settingsapi_adminpage');
}

function settingsapi_adminpage() {
    ?
    div class="wrap"
        ?php screen_icon(); ? h2Demo Plugin for Settings API/h2
        form action="options.php" method="post"
            ?php settings_fields('settingsapi_optiongroupname'); ?
            ?php do_settings_sections('settingsapi_pageslug'); ?
            ?php submit_button(); ?
        /form
    /div
    ?php
}
?

Is that possible with the settings API?

The register_setting() function accepts the third parameter as validation function call. However, it can be used to just fix the passed value but it accepts the form submission and saves the options. That is not what I'm looking for.

[Edit]

Okey, I'm almost there. This validates the submitted value with the callback function set in the register_setting() function. And if the value is invalid it leaves a flag, invalid, in the option array and displays a warning message.

However, there is one remaining issue. Otherwise, it is almost done.

  1. Once an empty value is set to the first input option, it shows the warning message. It is what we've achieved so far. And if the user leaves the page showing the warning, somehow the empty value is saved to the option. It should revert the previous value.

The code below is ready to use as a plugin. If you run it, you'll see what I'm talking about.

?php
/*
Plugin Name: Demo Verification Notice with Settings API
Description: Learning how to warn invalid values when submitting the form and take back the user to the setting page without saving the options.
Author: Teno
*/

add_action('admin_init', 'settingsapi_init');
function settingsapi_init(){
    register_setting( 'settingsapi_optiongroupname', 'settingsapi_optionname','validation_callback');

    add_settings_section('plugin_main', 'Section 1', 'settingsapi_sectiondescription', 'settingsapi_pageslug');
    add_settings_field('plugin_text_string_a', 'Option A', 'settingsapi_setting_string_a', 'settingsapi_pageslug', 'plugin_main');
    add_settings_field('plugin_text_string_b', 'Option B', 'settingsapi_setting_string_b', 'settingsapi_pageslug', 'plugin_main');
}

function settingsapi_sectiondescription() {
    echo 'pThis is a section description./p';
}
function settingsapi_setting_string_a() {
    $options = get_option('settingsapi_optionname');
    ?
    input type="hidden" name="settingsapi_optionname[submitted]" value="1" /
? print_r($options); ?br /
    input id="plugin_text_string" name="settingsapi_optionname[preview][option_a]" size="40" type="text" value="?php echo $options['submitted']  ? $options['preview']['option_a'] : $options['valid']['option_a']; ?" /
    ?php echo ($options['invalid']  $options['submitted'] ) ? 'font color="red"* cannot be blank./font' :'' ?
    ?php
} 
function settingsapi_setting_string_b() {
    $options = get_option('settingsapi_optionname');
    ?
? print_r($options); ?br /  
    input id="plugin_text_string" name="settingsapi_optionname[preview][option_b]" size="40" type="text" value="?php echo $options['submitted'] ? $options['preview']['option_b'] : $options['valid']['option_b']; ?" /
    ?php
}
// admin menu
add_action('admin_menu', 'plugin_admin_add_page');
function plugin_admin_add_page() {
    add_options_page('Custom Plugin Page', 'Demo Settings API Menu for Verification', 'manage_options', 'settingsapi_pageslug', 'settingsapi_adminpage');
}

function settingsapi_adminpage() {
    ?
    div class="wrap"
        ?php screen_icon(); ? h2Demo Plugin for Validation Message with Settings API/h2

        ?php
        $options = get_option('settingsapi_optionname');
        print_r($options);      // for debugging purpose
        if (!($options['invalid']  $options['submitted'])) {

            // update the correct option values
            $options['valid'] = is_array($options['valid']) ? $options['valid'] : array();  // if the options['valid'] is called for the first time, make it an array
            $options['valid'] = array_merge($options['valid'], $options['preview']);
            // $options['preview'] = '';    // initialize the preview option data. //-- this seems to cause a problem
            update_option('settingsapi_optionname', $options);
        }
        ?

        form action="options.php" method="post"
            ?php 
            settings_fields('settingsapi_optiongroupname');
            do_settings_sections('settingsapi_pageslug'); 

            // after displaying the form content, set the invalid flag and the subbmited flag to false
            $options['invalid'] = False;
            $options['submitted'] = False;      
            update_option('settingsapi_optionname', $options);  

            submit_button();
            ?          
        /form

    /div
        ?php 
            print_r($options);
        ?  
    ?php
}

function validation_callback($input){
    if (strlen(trim($input['preview']['option_a'])) == 0  $input['submitted']) {
        // $input['preview']['option_a'] = '';
        unset($input['preview']['option_a']);
        $input['invalid'] = True;   // -- this one is the problem. It seems to be called multiple times and setting the invalid flag to true when it's not necessary.
        add_settings_error('unique_identifyer',esc_attr('settings_updated'),__('Settings NOT saved.'),'error');
        add_action('admin_notices', 'print_errors');
    } else {
        $input['invalid'] = False;
    }
    return $input;
}

function print_errors(){
    settings_errors( 'unique_identifyer' );
}

?

[Edit]

It might be easier to do it without the Settings API. Here is a working example.

?php
/*
Plugin Name: Demo Verification Warning without Settings API
Description: Demo plugin demonstrating how to display a warning message when the user tries to save an invalid value in the option page.
Author: Teno
*/

// define constants
define("DEMOVERIFICATIONKEY", "demo_verification_option");

// create an option array
$arrOption = get_option(DEMOVERIFICATIONKEY);
if (!(is_array($arrOption))) {
    $arrOption = array(
        "tab1" = array(),
        "tab2" = array(),
        "tab3" = array()
    );
    update_option(DEMOVERIFICATIONKEY, $arrOption);
}

// admin menu
add_action('admin_menu', 'demo_verification_adminmenu');
function demo_verification_adminmenu() {
    add_options_page('Demo Plugin Menu for Verification without Settings API', 'Demo Plugin Menu for Verification without Settings API', 'manage_options', 'demo_verification_admin_menu', 'demo_verification_adminpage');
}
// admin page
function demo_verification_adminpage() {
    $options = get_option(DEMOVERIFICATIONKEY);
    print_r($_POST); // for debugging
    echo 'br /';
    if(isset($_POST[DEMOVERIFICATIONKEY]['tab1']['submitted'])  $_POST[DEMOVERIFICATIONKEY]['tab1']['submitted'] == 1){
        if (strlen(trim($_POST[DEMOVERIFICATIONKEY]['tab1']['option_a'])) == 0) {
            $options['tab1']['invalid'] = True;     
            echo 'div class="error settings-error"pOptions are not saved./p/div';
        } else {    
            $options = array_merge($options, $_POST[DEMOVERIFICATIONKEY]);
            update_option(DEMOVERIFICATIONKEY, $options);
            echo 'div class="updated"pUpdates are saved./p/div';
        }
    }   
    ?
    div class="wrap"
        ?php screen_icon(); ? h2Demo Plugin for Validation Message without Settings API/h2
        form method="post" action=""  ?php // 'action=""' means to send the form post data to this page itself. ?
            input type="hidden" name="?php echo DEMOVERIFICATIONKEY; ?[tab1][submitted]" value="1" /
            table class="form-table"
                tbody
                tr valign="top"
                    th scope="row"Option A/th
                    td
                        input name="?php echo DEMOVERIFICATIONKEY; ?[tab1][option_a]" size="40" type="text" value="?php echo $options['tab1']['invalid']  ? $_POST[DEMOVERIFICATIONKEY]['tab1']['option_a'] : $options['tab1']['option_a']; ?" /
                        ?php echo ($options['tab1']['invalid']  $options['tab1']['invalid'] ) ? 'font color="red"* cannot be blank./font' :'' ?
                    /td
                /tr
                tr valign="top"
                    th scope="row"Option B/th
                    td
                        input name="?php echo DEMOVERIFICATIONKEY; ?[tab1][option_b]" size="40" type="text" value="?php echo $options['tab1']['invalid'] ? $_POST[DEMOVERIFICATIONKEY]['tab1']['option_b'] : $options['tab1']['option_b']; ?" /
                    /td
                /tr
                /tbody
            /table
            ?php submit_button(); ?   
        /form     
    /div
    ?php
}
?

But in case if somebody can figure it out with the Settings API, please post the solution.

Topic settings-api validation verification Wordpress

Category Web


First add a validation callback to your register_settings:

register_setting( 'settingsapi_optiongroupname', 'settingsapi_optionname','validation_callback');

then define validation_callback:

function validation_callback($input){
    //check if all is good
    //If so then return the wanted value to be saved
    //If Not then hook your admin notice function and return null to be saved ex:
    if ($something){
        return $input;
    }else{
        add_settings_error('unique_identifyer',esc_attr('settings_updated'),__('Settings saved.'),'updated');
        add_action('admin_notices', 'print_errors');
        return null;
    }
}

and last define print_errors something like:

function print_errors(){
    settings_errors( 'unique_identifyer' );
}

and if nothing happens then try adding include_once 'options-head.php'; in your page

Update here is a plugin to test and see that it works just fine:

<?php
/*
Plugin Name: wpse62418
Plugin URI: http://en.bainternet.info
Description: answer to http://wordpress.stackexchange.com/questions/62418/verify-submitted-form-values-and-show-warning-messages-with-setting-api/62434
Version: 1.0
Author: Bainternet
Author URI: http://en.bainternet.info
*/


add_action('admin_init', 'settingsapi_init');
function settingsapi_init(){
    register_setting( 'settingsapi_optiongroupname', 'settingsapi_optionname','validation_callback');       //

    add_settings_section('plugin_main', 'Section 1', 'settingsapi_sectiondescription', 'settingsapi_pageslug');
    add_settings_field('plugin_text_string_a', 'Option A', 'settingsapi_setting_string_a', 'settingsapi_pageslug', 'plugin_main');
}

function settingsapi_sectiondescription() {
    echo '<p>This is a section description.</p>';
}
function settingsapi_setting_string_a() {
    $options = get_option('settingsapi_optionname');
    ?>
    <input type="hidden" name="settingsapi_optionname[submitted]" value="1" />
    <input id="plugin_text_string" name="settingsapi_optionname[preview][option_a]" size="40" type="text" value="<?php echo isset( $options['preview']['option_a']) ? $options['preview']['option_a'] : ''; ?>" />
    <?php
} 
// admin menu
add_action('admin_menu', 'plugin_admin_add_page');
function plugin_admin_add_page() {
    add_options_page('Custom Plugin Page', 'Demo Settings API Menu for Verification', 'manage_options', 'settingsapi_pageslug', 'settingsapi_adminpage');
}

function settingsapi_adminpage() {
    ?>
    <div class="wrap">
        <?php screen_icon(); ?> <h2>Demo Plugin for Validation Message with Settings API</h2>

        <?php
        $options = get_option('settingsapi_optionname');
        print_r($options);      // for debugging purpose
        ?>

        <form action="options.php" method="post">
            <?php 
            settings_fields('settingsapi_optiongroupname');
            do_settings_sections('settingsapi_pageslug'); 

            // after displaying the form content, set the invalid flag and the subbmited flag to false

            submit_button(); 
            ?>
        </form>

    </div>
        <?php 
            print_r($options);
        ?>  
    <?php
}

function validation_callback($input){
    add_settings_error('unique_identifyer',esc_attr('settings_updated'),__('Settings NOT saved.'),'error');
    add_action('admin_notices', 'print_errors');
    return $input;
}

function print_errors(){
    settings_errors( 'unique_identifyer' );
}

Once the validation callback is invoked, you're too late in the process to do form validation, because the form has already been submitted. You're likely going to have to look at a javascript form-validation solution that happens on-page, and before the form is submitted.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.