Can’t save options

I created theme options page using Settings API, everything works fine but I can’t save options. I tried to figure it out where I missed something but I failed. Any idea what can cause this problem?

Here’s code of my options page

<?php
/**
 * This functions registers default options values for Evolutionary theme 
 * settings
 */
function ev_theme_settings_defaults() {
    $options = array(
        'color_scheme' => 'blue',
        'copyright' => '',
        'nav_hide_home' => false,
        'nav_hide_sec' => false,
        'nav_show_lvl' => false,
        'featured_show' => false,
        'featured_pause' => false,
        'featured_speed' => 5,
        'ad1_link' => '',
        'ad1_image' => '',
        'ad2_link' => '',
        'ad2_image' => '',
        'ad3_link' => '',
        'ad3_image' => '',
        'ad4_link' => '',
        'ad4_image' => ''
    );

    return $options;
    // Change to apply_filters( 'ev_theme_settings_defaults', $options );
}

/**
 * Create helper function for theme colors
 */
function ev_get_valid_color_schemes(){
    $color_schemes = array(
        'blue' => __( 'Blue', 'evolutionary' ),
        'green' => __( 'Green', 'evolutionary' ),
        'red' => __( 'Red', 'evolutionary' ),
        'black' => __( 'Black', 'evolutionary')
    );

    return $color_schemes;    
} 

/**
 * Setup initial theme options
 */
function ev_options_init() {
    // Set options equal to defaults
    global $ev_options;
    $ev_options = ev_theme_settings_defaults();
    if ( false === $ev_options ) {
        $ev_options = ev_theme_settings_defaults();
    }
    update_option( 'theme_evolutionary_options', $ev_options );
}

add_action( 'after_setup_theme', 'ev_options_init', 9 );

/**
 * Add theme options page to admin menu
 */
function ev_menu_options() {
    add_theme_page( __( 'Theme Options', 'evolutionary' ), __( 'Theme Options', 'evolutionary' ), 'edit_theme_options', 'evolutionary-settings', 'ev_admin_options_page' );
}

add_action( 'admin_menu', 'ev_menu_options' );

/**
 * Register theme options
 */
function ev_register_options() {
    register_setting( 'theme_evolutionary_options', 'theme_evolutionary_options', 'ev_options_validate' );

/**
 * Defining settings sections and fields
 * fist setting creates sections for general options
 */
add_settings_section( 'ev_settings_general_options', __( 'General Options', 'evolutionary' ), 'ev_settings_general_options', 'evolutionary' );

// Creates section for navigation options
add_settings_section( 'ev_settings_nav_options', __( 'Navigation', 'evolutionary' ), 'ev_settings_nav_options', 'evolutionary' );

// Section for featured post options
add_settings_section( 'ev_settings_featured_options', __( 'Featured Posts', 'evolutionary' ), 'ev_settings_featured_options', 'evolutionary' );

// Section for Advertising options
add_settings_section( 'ev_settings_ad_options', __( 'Advertising', 'evolutionary' ), 'ev_settings_ad_options', 'evolutionary' );

/**
 * Created empty callbacks for setions
 */
function ev_settings_general_options() {
    // Put callback code here
}
function ev_settings_nav_options() {
    // callback
}
function ev_settings_featured_options() {
    // callback
}
function ev_settings_ad_options() {
    // callback
}

/**
 * Registered fields
 */
add_settings_field( 'ev_settings_copyright_field', __( 'Copyright Name', 'evolutionary' ), 'ev_settings_copyright_field', 'evolutionary', 'ev_settings_general_options' );

add_settings_field( 'ev_settings_colors_field', __( 'Theme Color', 'evolutionary' ), 'ev_settings_colors_field', 'evolutionary', 'ev_settings_general_options' );

/**
 * Fields Callbacks
 */
function ev_settings_copyright_field() {
    $ev_options = get_option( 'theme_evolutionary_options' );
    //var_dump( $ev_options );
    ?>
    <input name="theme_evolutionary_options[copyright]" type="text" class="regular-text" value="<?php esc_attr_e( $ev_options['copyright'] ); ?>"  />
<?php }
// Callback for colorscheme
function ev_settings_colors_field() {
    $ev_options = get_option( 'theme_evolutionary_options' );
    $color_schemes = ev_get_valid_color_schemes();

    echo '<select name="theme_evolutionary_options[color_scheme]">';

    foreach( $color_schemes as $value => $caption ) :
?>
        <option value="<?php echo $value; ?>" <?php selected( $value, $ev_options['color_scheme'] ); ?>><?php echo $caption; ?></option>

<?php 
    endforeach;

    echo '</select>';
}

} // ev_register_options
add_action( 'admin_init', 'ev_register_options' );    

/**
 * Creating options page HTML output
 */
function ev_admin_options_page() { ?>

    <div class="wrap">
       <?php if ( isset( $_GET['settings-updated'] ) ) {
                echo "<div class="updated"><p>Theme settings updated successfully.</p></div>";
        } ?>
        <?php screen_icon(); ?>
        <h2><?php _e( 'Theme Options', 'evolutionary' ); ?></h2>
        <form action="options.php" method="post">
        <?php 
        settings_fields( 'theme_evolutionary_options' );
        do_settings_sections( 'evolutionary' );
        ?>

            <input name="submit" type="submit" class="button-primary" value="<?php _e( 'Save Settings', 'evolutionary' ) ?>" />
            <input name="reset" type="submit" class="button-secondary" value="<?php _e( 'Reset Settings', 'evolutionary' ) ?>" />
        </form>
    </div>
<?php }

function ev_options_validate( $input ) {
    $ev_options = get_option( 'theme_evolutionary_options' );
    $valid_input = $ev_options;

    $ev_options['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
    $ev_options['copytright'] = wp_kses_data( $ev_options['copyright'] );

    return $valid_input;
}

3 Answers
3

@Mamaduka:

Here is why your settings aren’t updating. Your validation function is wrong. To wit:

function ev_options_validate( $input ) {
    $ev_options = get_option( 'theme_evolutionary_options' );
    $valid_input = $ev_options;

    $ev_options['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
    $ev_options['copytright'] = wp_kses_data( $ev_options['copyright'] );

    return $valid_input;
}

You’re updating $ev_options, but returning $valid_input. You need to be updating $valid_input, not $ev_options.

Try this instead:

function ev_options_validate( $input ) {
    $ev_options = get_option( 'theme_evolutionary_options' );
    $valid_input = $ev_options;

    $valid_input['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
    $valid_input['copytright'] = wp_kses_data( $ev_options['copyright'] );

    return $valid_input;
}

See if that fixes your problem?

EDITED TO ADD:

Your next problem in the validation function is that you’re comparing $ev_options to/against itself, when you need to be evaluating $input against $valid_input.

Instead of this:

function ev_options_validate( $input ) {
    $ev_options = get_option( 'theme_evolutionary_options' );
    $valid_input = $ev_options;

    $valid_input['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
    $valid_input['copytright'] = wp_kses_data( $ev_options['copyright'] );

    return $valid_input;
}

Try this:

function ev_options_validate( $input ) {
    $ev_options = get_option( 'theme_evolutionary_options' );
    $valid_input = $ev_options;

    $valid_input['color_scheme'] = array_key_exists( $input['color_scheme'], ev_get_valid_color_schemes() ) ? $input['color_scheme'] : 'blue';
    $valid_input['copytright'] = wp_kses_data( $input['copyright'] );

    return $valid_input;
}

Specifically, change this:

$valid_input['color_scheme'] = array_key_exists( $ev_options['color_scheme'], ev_get_valid_color_schemes() ) ? $ev_options['color_scheme'] : 'blue';
$valid_input['copytright'] = wp_kses_data( $ev_options['copyright'] );

To this:

$valid_input['color_scheme'] = array_key_exists( $input['color_scheme'], ev_get_valid_color_schemes() ) ? $input['color_scheme'] : 'blue';
$valid_input['copytright'] = wp_kses_data( $input['copyright'] );

And then, I think, your options should work.

@TheDeadMedic:

The Settings API handles looking at any $POST data. That’s not the problem.

Regarding the default-settings updating on init, here’s my original, example code:

function oenology_options_init() {
     // set options equal to defaults
     global $oenology_options;
     $oenology_options = get_option( 'theme_oenology_options' );
     if ( false === $oenology_options ) {
          $oenology_options = oenology_get_default_options();
     }
     update_option( 'theme_oenology_options', $oenology_options );
}
// Initialize Theme options
add_action('after_setup_theme','oenology_options_init', 9 );

And here’s Mamaduka’s code:

function ev_options_init() {
    // Set options equal to defaults
    global $ev_options;
    $ev_options = ev_theme_settings_defaults();
    if ( false === $ev_options ) {
        $ev_options = ev_theme_settings_defaults();
    }
    update_option( 'theme_evolutionary_options', $ev_options );
}

add_action( 'after_setup_theme', 'ev_options_init', 9 );

Do you see the difference? There is a critical change from oenology_options_init() to ev_options_init(), to wit:

This:

global $oenology_options;
$oenology_options = get_option( 'theme_oenology_options' );

Versus this:

global $ev_options;
$ev_options = ev_theme_settings_defaults();

Thus, in ev_options_init(), the function never actually does anything, because of the change.

Leave a Comment