WordPress.org

Make WordPress Core

Opened 4 years ago

Closed 4 years ago

#36633 closed enhancement (maybelater)

Customizer Doesn't Save Defaults in The Database for a Theme

Reported by: mrahmadawais Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.6
Component: Customize Keywords: dev-feedback
Focuses: Cc:

Description

Customizer doesn't save setting's default parameters in the database until unless the end user opens up the customizer and saves the settings.

The default property only works when the settings are saved at least once. When a user installs the theme with customizer settings that enable or disable features, there are no defaults values for settings saved in the DB until unless user opens the customizer and saves the settings.

Here look at this. I am using a radio control to enable or disable the social icons box in the header. When theme is first installed there is no social box even when the setting's default is set to enable.

https://i.imgur.com/N2jmvO4.png

and here is the social box being displayed in the header right when I click customize (Note: I have not even saved the settings yet).

https://i.imgur.com/ynQxWSv.png

Change History (7)

#1 @mrahmadawais
4 years ago

  • Keywords dev-feedback 2nd-opinion added

If someone from Customizer component maintainers could confirm that, I would love to contribute this enhancement to the core for WP 4.6.

NOTE: Check with `radio` type control.

I think this issue is related to the radio type, or maybe all types that have choices array.

Last edited 4 years ago by mrahmadawais (previous) (diff)

#2 follow-up: @kuus
4 years ago

  • Keywords close added; 2nd-opinion removed
  • Resolution set to wontfix
  • Status changed from new to closed

Hello, for what I understood from your comment this is not a bug and does not have anything to do with the customizer. Default values are not meant to be stored in the database, in fact themes should use 'sane defaults' (see article https://make.wordpress.org/themes/2014/07/09/using-sane-defaults-in-themes/).

In your specific case I guess you should simply show the social box unless the value retrieved is true, for instance (pseudo code): <?php if ( ! get_theme_mod('hide_box') ) { ?>box template<?php } ?>

feel free to reopen if I misunderstood your ticket

Last edited 4 years ago by kuus (previous) (diff)

#3 in reply to: ↑ 2 @mrahmadawais
4 years ago

Replying to kuus:

Hello, for what I understood from your comment this is not a bug and does not have anything to do with the customizer. Default values are not meant to be stored in the database, in fact themes should use 'sane defaults' (see article https://make.wordpress.org/themes/2014/07/09/using-sane-defaults-in-themes/).

In your specific case I guess you should simply show the social box unless the value retrieved is true, for instance (pseudo code): <?php if ( ! get_theme_mod('hide_box') ) { ?>box template<?php } ?>

feel free to reopen if I misunderstood your ticket

Well, think about this. I have 10 social icons in this theme and I have enabled 5 of them by default while the rest of them are false by default. If Customizer default option is not meant to be saved in the database, it is kind of against DRY. I will have to keep defaults in the customizer as well as in the theme file where they are being used. One set of default options should be enough, what do you suggest in this case?

BTW I didn't report a bug, it's tagged under enhancement. I know and have read sane defaults article before.

#4 @kuus
4 years ago

  • Resolution wontfix deleted
  • Status changed from closed to reopened

BTW I didn't report a bug, it's tagged under enhancement. I know and have read sane defaults article before.

you are right I'm sorry! I'm pretty new to core.trac

I see your point, and actually I'm working on a plugin that among other things solves this issue of having the defaults in multiple places. I'll let you know when I'll release it if you want, sorry but at the moment I don't have a quick and dry solution..

Last edited 4 years ago by kuus (previous) (diff)

#5 follow-up: @westonruter
4 years ago

@mrahmadawais thanks for explaining. Yes, I can see how this would be confusing. If this were to be fixed, the approach I'd take would be to register any settings that lack values saved in the database as dirty up-front. This would ensure that when the user saves the Customizer state, all of these settings would be saved.

But, I'm not entirely sure that there is a change that should be made. Take, for example, get_theme_mod() and get_option(). Both of these also take a $default argument. If a theme uses these functions and supplies a default value, then these would indeed be duplicated with any corresponding Customizer settings that get registered. But wouldn't this be the right thing to do? If someone activates a theme and never opens the Customizer, then all of these settings wouldn't be set in the DB either.

What I think themes should do instead, then, is to perhaps have a theme config array that can be re-used both in the get_option()/get_theme_mod() calls and when registering Customizer settings, to be used as the $default in each case.

For example:

<?php
$acme_theme_defaults = array(
        'phone_number' => '999-999-9999',
);

add_action( 'wp_footer', function() use ( $acme_theme_defaults ) {
        ?>
        <p>
                You should give us a call! <?php echo esc_html( get_theme_mod( 'phone_number', $acme_theme_defaults['phone_number'] ) ) ?>
        </p>
        <?php
} );

add_action( 'customize_register', function( WP_Customzie_Manager $wp_customize ) use ( $acme_theme_defaults ) {
        $wp_customize->add_setting( 'acme_phone_number', array(
                'type' => 'theme_mod',
                'default' => $acme_theme_defaults['phone_number'],
        ) );

        $wp_customize->add_control( 'acme_phone_number', array(
                'type' => 'text',
        ) );
} );

#6 in reply to: ↑ 5 @mrahmadawais
4 years ago

Replying to westonruter:

@mrahmadawais thanks for explaining. Yes, I can see how this would be confusing. If this were to be fixed, the approach I'd
.....

Yup! The default array makes a lot of sense. That way if I really want to initialize the options, I can otherwise it simplifies things.

P.S. This is what I am doing at the moment with the defaults array.

<?php
/**
 * Initialize Customizer settings with defaults.
 *
 * @since 1.0.0
 */
if ( ! function_exists( 'vr_customizer_init_defaults' ) ) {
        add_action( 'customize_register', 'vr_customizer_init_defaults' );
        function vr_customizer_init_defaults( $wp_customize ) {
                // Just in case.
                global $wp_customize;

                // Be safe.
                if ( ! isset( $wp_customize ) ) {
                        return;
                }

                $vr_settings_array = array(
                        'vr_hide_call',
                        'vr_hide_fb',
                        'vr_fb_url',
                        'vr_hide_twt',
                        'vr_twt_url',
                        'vr_hide_gplus',
                        'vr_gplus_url',
                        'vr_hide_skp',
                        'vr_skp_url',
                        'vr_hide_li',
                        'vr_li_url',
                        'vr_hide_ytube',
                        'vr_ytube_url',
                        'vr_hide_insta',
                        'vr_insta_url',
                        'vr_hide_vim',
                        'vr_vim_url'
                );

                foreach ( $vr_settings_array as $id ) {
                        $setting = $wp_customize->get_setting( $id );

                        $value = get_theme_mod( $id );
                        if ( ! isset( $value ) || false == $value ) {
                                set_theme_mod( $setting->id, $setting->default );
                        }
                } // foreach ended.
        } // vr_customizer_init_defaults() ended.
} // function_exists() ended.

#7 @westonruter
4 years ago

  • Keywords close removed
  • Milestone Awaiting Review deleted
  • Resolution set to maybelater
  • Status changed from reopened to closed
Note: See TracTickets for help on using tickets.