How to get control choices from $setting object passed to sanitize_callback

The question:

Example Code

Working with the Customizer API.

Setting added (example) like so:

    $wp_customize->add_setting( 'theme_oenology_options[' . $option_parameter['name'] . ']', array(
        'default'           => $option_parameter['default'],
        'type'              => 'option',
        'sanitize_callback' => 'oenology_sanitize_' . $option_parameter['sanitize']
    ) );

Control added (example) like so:

        $wp_customize->add_control( 
            'oenology_' . $option_parameter['name'], 
            $customizer_control_parameters 
        );

Note: $customizer_control_parameters is an array defined elsewhere. For select-type controls (select, radio, radio-image, etc.) it includes a 'choices' key.

Sanitize callback defined (example) like so:

function oenology_sanitize_select( $input ) {
    return sanitize_key( $input );
}

Everything works flawlessly in the Customizer. The control is displayed, the setting is configurable, and the sanitization works.

Problem

All good so far, but it would be better to whitelist the setting against pre-defined choices in $wp_customize->add_control(). Let’s use the second parameter passed to 'sanitize_callback', $setting, to get the 'choices' defined in the control!

Core reference:

return apply_filters( "customize_sanitize_{$this->id}", $value, $this );

Solution Attempts

function oenology_sanitize_select( $input, $setting ) {
    $input = sanitize_key( $input );
    $choices = array(); // See below
    return ( array_key_exists( $input, $choices ) ? $input : $setting->default );
}

Problem: using either of the two methods below does not return the array of choices passed to $wp_customize->add_control():

  1. Using $wp_customize global object:

    global $wp_customize;
    $control = $wp_customize->get_control( $setting->id );
    $choices = $control->choices;
    
  2. Using $setting->manager object:

    $choices = $setting->manager->get_control( $setting->id )->choices;
    

In both cases, get_control( $setting->id ) returns a null, instead of an object.

Question

How do I get 'choices' from $wp_customize->get_control(), using the $this object passed to "customize_sanitize_{$this->id}"?

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

This is correct:

$control = $setting->manager->get_control($setting->id);
$choices = $control->choices;

However, in your example, $setting->id will be theme_oenology_options[name].

So, get_control('theme_oenology_options[name]') will return null because there’s no control with that name. You gave the control the id of oenology_name instead.

I always give the same ID to settings and their matching controls for that reason.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment