WordPress.org

Theme Review Team

Tagged: Settings API Toggle Comment Threads | Keyboard Shortcuts

  • Justin Tadlock 11:45 pm on November 26, 2014 Permalink |
    Tags: , Settings API,   

    Theme Mods API or Settings API? 

    A few days ago, Chip Bennett wrote a good tutorial on the APIs related to theme options and broke down how those APIs can/should be used depending on the context. If anyone can really go in depth with theme options, it’s Chip. I’m hoping we see more from him on theme options in the future. I highly encourage reading his post to make sure you have the foundation you need.

    In this post, I want to cover a question that has been popping up, particularly about the Theme Mods vs. Settings and which to use.

    Essentially, we allow three different methods of handling theme options on the repository (technically, there are other methods, but we allow three):

    • Customizer API + Theme Mods
    • Customizer API + Settings API
    • Theme options page created with the Settings API

    The customizer is so much easier to use and requires a lot less code. It’s something I strongly recommend. It’s also what I’ll be focusing on as I write more about theme options. This post is going to focus on whether you should use the Theme Mods API or the Settings API for storing options.

    Theme Mods

    The thing many theme authors get hung up on is that theme mods are saved on a per-theme basis. So, this means when you switch child themes, any theme mod options will need to be saved again for the new child theme. Sometimes, users might even see this as “losing their settings”.

    This is both a blessing and a curse. I love it because it allows my users to have seasonal or holiday child themes. Imagine you wanted to have a child theme specifically for the Christmas season with its own color scheme. It’s nice to be able to change those color options just for the Christmas child theme.

    What happens when you switch back to your regular theme in January? Well, it still has all of its unique options saved for it. There’s no work involved except for switching child themes.

    The other nice thing is that core WP has hooks already built in for each new theme mod you create. That’s very nice for child theme authors who want to quickly filter options in the parent theme.

    Settings API

    I’m less of a fan of the Settings API because it means that an option is saved based on the parent theme. The great thing about it is that users only have to save options once and not save them again if they switch child themes (technically, you can get around that if anyone wants me to explain the code).

    Going back to the Christmas theme example: What happens when you switch to a Christmas child theme? In this scenario, you’d have to change your colors. Then, you’d have to change them again when switching back to your non-holiday child theme.

    However, not all theme options need to be changed when a user switches child themes. Some options make more sense to stay the same, regardless of child theme.

    What about a combination?

    Actually, you can use a combination of both the Theme Mods API and Settings API with the customizer. It’s not an either/or thing. That’s just another example of its awesomeness. I even encourage this practice in some situations.

    I imagine things like colors and fonts would generally make more sense as theme mods. But, an option to either show excerpts or content on the front page might be better served via the Settings API.

    Each option should really be given this consideration rather than blindly doing one or the other.

     
    • Weston Ruter 11:53 pm on November 26, 2014 Permalink | Log in to Reply

      Customizer for the win!

    • nikeo 7:37 am on November 27, 2014 Permalink | Log in to Reply

      Thanks for your post @greenshady. I found the child theme example really interesting to demonstrate the “dynamic” possibilities offered by theme mods vs settings API.

    • ro_sev 11:48 pm on November 27, 2014 Permalink | Log in to Reply

      thanks

    • mojaray2k 1:51 am on November 28, 2014 Permalink | Log in to Reply

      I am using the settings API for more site info features like social media links and other global data to be displayed site wide. But the Theme Mods API just gives me as a developer more ability to involve a designer and end user to truly control the final look and feel of their site.

    • Edward R. Jenkins 1:43 am on December 10, 2014 Permalink | Log in to Reply

      Hi Justin — I agree that the theme_mod setup is both a blessing and a curse. I’m using the customizer exclusively for my latest theme, and I was a little frustrated with the way WP handles it. But after playing with it for a bit, I can certainly see why it’s done that way.

  • Chip Bennett 11:19 pm on November 24, 2014 Permalink |
    Tags: , Options API, Settings API,   

    Understanding the APIs Related to Theme Options 

    There seems to be a great deal of confusion regarding the various APIs involved with Theme options, especially regarding the interactions among those APIs. This confusion is obvious in discussions involving the Customizer. This post will attempt to explain the various APIs and how they work together.

    The first thing to understand is the various interactions with options: storing options in the database, retrieving options from the database, and user configuration of options.

    Storing and Retrieving Options

    WordPress has two APIs for storing and retrieving Theme options: the Options API and the Theme Modification (Theme Mods) API. The Options API is the “granddaddy” API, used by core and Plugins, as well as Themes. The Theme Mods API is a Theme-specific API.

    The Options API uses the add_option() and update_option() functions to store options to the database, and get_option() to retrieve options from the database. The Theme Mods API uses the set_theme_mod() to store options to the database, and get_theme_mod() and get_theme_mods() to retrieve options from the database. Neither API deals with user configuration (e.g. Settings pages) of options.

    User Configuration of Options

    There are essentially three ways to allow users to configure Theme options: a Settings API-generated settings page, a custom settings page, and the Customizer API. Both a settings page and the Customizer display options retrieved by either the Settings API or the Theme Mods API, then return user-configured settings to that same API for storage in the database.

    (Note: where the Theme Review Guidelines formerly recommended using the Settings API, that recommendation applied to using the Settings API to generate the settings page, rather than the Theme creating a custom settings page. That recommendation has been superseded by the recommendation to use the Customizer.)

    The Settings API includes a robust set of functions to generate a Settings page, but is missing some key elements such as default markup for settings fields, and standard sanitization/validation based on option data type. This void is frequently filled by the various option framework libraries available. Using such frameworks avoids the necessity of the Theme developer to roll their own code. These frameworks generally also handle the sometimes complex callback structure needed to implement the Settings API fully. (And no joke; fully implementing the Settings API is so complex that I wrote a ten-page tutorial on it a few years ago.)

    Until the Customizer, the only other option was a completely custom Theme settings page. These used to be all the rage (and can still be found in many options frameworks), and were promoted as a Theme “feature”. All they really did was add a non-core UI and increase the learning curve for Theme developers and users alike. That’s why the Theme Review Guidelines used to recommend use of the Settings API to generate Theme settings pages.

    Now, for Themes that opted to use the Theme Mods API, a custom Theme settings page was the only option. The Theme Mods API is, overall, probably a better and easier API to understand and to use – but it did not include an API for creating a settings page.

    Customizer API

    Now, a third option exists: the Customizer.

    It is important to keep in mind here that the Customizer is not an API for storing or retrieving settings; it is an API for user configuration of settings. It is not a replacement for either the Settings API or the Theme Mods API for storing/retrieving options; it is a replacement for Theme settings pages. The Customizer does not store options to or retrieve options from the database. It merely displays options retrieved by either the Theme Mods API or the Settings API, and returns settings to either the Theme Mods API or the Settings API for storage in the database.

    This is a very important distinction to remember, because, while the Customizer defaults to using the Theme Mods API, it can be used with either the Theme Mods API or the Settings API. This flexibility is important for existing Themes as well as for new Themes. Developers of existing Themes that use the Settings API, and who want to migrate away from settings pages and toward use of the Customizer can do so quite easily. And Developers of new Themes that want to take advantage of the Customizer from the beginning can do so just as easily.

    Key Points

    1. Theme Mods API and Options API are used to store/retrieve options
    2. Settings pages and the Customizer are used to allow users to configure options
    3. The Customizer can replace a Settings page and the Settings API, but cannot replace either the Theme Mods API or the Options API
    4. The Customizer can be used on top of either the Theme Mods API or the Options API
    5. Themes that currently use the Settings API, either directly or using an options framework library, can use the Customizer without changing any of the underlying options code already in use
    6. Themes that currently use a Settings page with the Settings API can add Customizer support without impacting or removing the current Settings page
    7. New Themes are recommended to use the Customizer with the Theme Mods API
     
    • Emil Uzelac 5:08 am on November 25, 2014 Permalink | Log in to Reply

      Thanks Chip, this was refreshing and much needed! Hopefully we will see more of you around :)

    • Ulrich 5:37 am on November 25, 2014 Permalink | Log in to Reply

      How is the theme mods API better than the settings API? Is it possible to use a single array with the theme mods API?

    • Jose Castaneda 6:04 am on November 25, 2014 Permalink | Log in to Reply

      Yes, it is.

    • Edward Caissie 2:03 pm on November 25, 2014 Permalink | Log in to Reply

      Great to hear your voice again. Thanks for this post!

    • Thomas from ThemeZee 2:31 pm on November 25, 2014 Permalink | Log in to Reply

      Great Post, thank you Chip.

      I have switched from settings pages to the Customizer a few months ago and use it in combination with the Settings API to retrieve options.

      Are there any reasons why it is recommended to use Customizer + Theme Mods API? I know it is slightly easier to implement, but I don’t see any other advantages.

      One major downside of the Theme Mods API was that it seems to save options based on the theme slug. It had the effect that users had to re-configure their settings when they choose to use a child theme or switched from the Lite version to our upsell themes.

      • Justin Tadlock 7:48 pm on November 25, 2014 Permalink | Log in to Reply

        Configuring settings on a per-theme basis is actually an advantage with using Theme Mods. Imagine you made a theme and users wanted to change their child theme based on the season or holidays (spring, summer, Christmas, etc.). See, they might have specific settings just for their Christmas child theme but different settings for their spring child theme. If you use the Settings API, they’ll have to remember their settings each time they want to change child themes rather than having them stored on a per-theme basis.

        Using Theme Mods is also really powerful for child theme developers who need to overwrite default settings. I encourage you to check out some of the child themes for Saga and Stargazer, two recent themes of mine that make use of this technique.

        There’s also a good case to be made for using a combination of the Settings API and the Theme Mods API. Settings that wouldn’t need to change can use the Settings API (e.g., whether to show an author info box) and settings that might need to change can use the Theme Mods API (e.g., colors, fonts).

        • Ashley Shaw 8:05 am on November 26, 2014 Permalink | Log in to Reply

          Great input Justin, thanks. We will definitely consider your advice along with Chips post.

        • Thomas from ThemeZee 4:05 pm on November 26, 2014 Permalink | Log in to Reply

          Thanks Justin, that is a good point I haven’t considered. I will check some of the child themes for Stargazer, because I didn’t know that Theme Mods API settings can be overwritten that easily.

          I guess it depends on the use case if settings per-theme basis are good or bad for the end user. Maybe the best way really is a combination of both Settings and Theme Mods API as you suggested.

        • Philip Arthur Moore 10:36 am on November 27, 2014 Permalink | Log in to Reply

          Love this explanation.

    • Chip Bennett 10:10 pm on December 1, 2014 Permalink | Log in to Reply

      That awkward moment when you remember that you’ve incorrectly used “Settings API” and “Options API” interchangeably for years, and then put that in a tutorial. Options API != Settings API. Post is updated. Thanks, @kobenland!

  • Chip Bennett 1:22 am on July 9, 2014 Permalink |
    Tags: , sane defaults, Settings API,   

    Using Sane Defaults in Themes 

    With the release of WordPress 3.9, one of the changes to the Theme Review Guidelines is that Themes must use sane defaults. That means that Themes must not write default setting values to the database. For many Themes, this may seem like a major change; but it doesn’t have to be. This post will step through a few ways to implement sane defaults.

    Portability/DRY

    To make this method easier, put all of your defaults inside a function:

    function themeslug_get_option_defaults() {
    	$defaults = array(
    		'option_1' => 'value_1',
    		'option_2' => 'value_2',
    		'option_3' => 'value_3'
    	);
    	return apply_filters( 'themeslug_option_defaults', $defaults );
    }
    

    (Note: by making the return valuable filterable, the Theme defaults can be easily overridden by a Child Theme or Plugin.)

    We’ll make use of this function later.

    Options API

    Most Themes use the Options API, and will use get_option() to put Theme settings into a global:

    $themeslug_options = get_option( 'theme_themeslug_options' );
    

    Knowing that this get_option() caall will return FALSE if the option has not yet been saved to the database, Theme developers have taken to saving default values to the database as part of Theme initialization, like so:

    if ( false == get_option( 'theme_themeslug_options' ) ) {
    	update_option( 'theme_themeslug_options', themeslug_get_option_defaults() );
    }
    $themeslug_options = get_option( 'theme_themeslug_options' );
    

    But this is entirely unnecessary. And everything needed to implement a better solution already exists.

    As a first step, consider that get_option() includes a second parameter, which specifies the default value to return, if nothing is returned from the database:

    get_option( $name, $default );
    

    So, the simplest solution is merely to tell get_option() to return the defaults, using the function we previously defined:

    $themeslug_options = get_option( 'theme_themeslug_options', themeslug_get_option_defaults() );
    

    This works, but isn’t perfect. It will return the Theme-defined defaults if the user hasn’t saved settings to the databse. But if later versions of the Theme add, remove, or change options, this might break, since the return value is either/or: either the database-saved setting, or else the defaults. So, if the user saves settings, and then a new setting is added in a later Theme version, the new setting value won’t be included in $themeslug_options unless/until the user saves settings again.

    The solution is to merge the arrays, rather than to return one or the other. WordPress has a core function specifically for this purpose: wp_parse_args(), which will use the settings array, and “fill in the blanks” with the defaults array:

    wp_parse_args( $settings, $defaults );

    Caveat: bearing in mind that wp_parse_args() expects both parameters to be arrays, and knowing that get_option() returns FALSE by default, be sure to specify get_option() returns an empty array by default: get_option( ‘theme_themeslug_options’, array() ); otherwise, wp_parse_args() will (might – see note below) choke if the user hasn’t saved settings to the database.

    The construct will look something like this:

    $themeslug_options = wp_parse_args( 
        get_option( 'theme_themeslug_options', array() ), 
        themeslug_get_option_defaults() 
    );
    

    This is perhaps the simplest, most elegant way to implement sane defaults.

    (Note: according to Otto, passing an empty arrayy() as the second parameter to get_option() isn’t necessary. In his words: “The wp_parse_args() function checks for the first parameter to be an object or an array. If it’s neither, then it calls wp_parse_str on it, because it can take a GET URL-like array of parameters too. The wp_parse_str() function calls PHP’s parse_str on it, and does a deep strip_slashes if magic quotes is on, then filters the result. So, because false maps to the empty string, parse_str will return an empty array for it, so passing false to wp_parse_args should be A-OK and probably has been like that for a very long time. Doesn’t hurt to add the empty array(), but doesn’t really change anything.” YMMV.)

    Theme Modification API

    Using the Theme Modification API (get_theme_mod()/get_theme_mods()) is fairly similar.

    An individual setting can be called via:

    get_theme_mod( $name, $default );
    

    But perhaps more useful, all settings can be called via:

    $themeslug_options = get_theme_mods();
    

    Since get_theme_mods() returns an array, you can use the same technique as with Options API settings:

    $themeslug_options = wp_parse_args( 
        get_theme_mods(), 
        themeslug_get_option_defaults() 
    );
    

    Portability/DRY (Part 2)

    To be able to use this method throughout the Theme, wrap the wp_parse_args() call inside a function:

    function themeslug_get_options() {
        // Options API
        return wp_parse_args( 
            get_option( 'theme_themeslug_options', array() ), 
            themeslug_get_option_defaults() 
        );
        // Theme Mods API:
        /*
        return wp_parse_args( 
            get_theme_mods(), 
            themeslug_get_option_defaults() 
        );
        */
    }
    

    Then, wherever you need access to Theme options:

    $themeslug_options = themeslug_get_options();
    

    From there, you can globalize $themeslug_options, or cache/transient it, etc. When you need to add a new option, simply add the new option default to the defaults array, and the Theme will handle it automatically.

     
    • Justin Tadlock 2:05 am on July 9, 2014 Permalink | Log in to Reply

      No need for the custom filter hook there on the defaults. Child theme authors can simply filter 'default_option_' . $option if they need to overwrite this.

      • Chip Bennett 12:32 pm on July 9, 2014 Permalink | Log in to Reply

        But that only works if the option is not yet set in the database, right? In which case, it’s a bit more fragile, and wouldn’t work in the case of a Theme (or Child Theme) adding a new option in a later version of the Theme.

        • David Gwyer 12:15 pm on November 14, 2014 Permalink | Log in to Reply

          You can filter the value of an existing option with the ‘option_’ . $option filter hook if you want to filter the options stored in the db.

          https://core.trac.wordpress.org/browser/tags/4.0/src/wp-includes/option.php#L112

          But I also like the idea of being able to filter the defaults array which haven’t been merged with the options yet.

        • Justin Tadlock 8:38 pm on November 27, 2014 Permalink | Log in to Reply

          I somehow missed Chip’s reply. Yep, you can filter option_{$option} if it’s already been saved. Then, check if the new setting is there in the array.

          Either method works fine. A hook on the defaults array will probably be easier for most people to understand.

          All of this makes me want to use the Theme Mods API anyway where each setting will have a unique filter hook.

    • David Gwyer 2:09 pm on November 14, 2014 Permalink | Log in to Reply

      Whilst looking over the above code it made me wonder if there is a case for core to merge defaults and options arrays together automatically, in get_option() or add_option() / update_option().

      If all themes are encouraged to handle defaults as described above anyway then why not make it part of core ensuring themes always had correct options entries even when new options were added to the defaults array.

      This would have the added benefit of not requiring themes to globalize/cache theme by taking advantage of the fact that results from get_option() are always cached. This is important because if theme options are updated anywhere between defining the global options variable and referencing it in code then you could be working with potentially invalid options data.

    • kevinhaig 6:46 pm on November 27, 2014 Permalink | Log in to Reply

      A little late for this comment, but when using the setting_API, and Customizer, all defaults are saved anyway. If that is the case why jump through all these hoops, and just save the options immediately the first time they are called.?

      • Justin Tadlock 8:43 pm on November 27, 2014 Permalink | Log in to Reply

        They’re actually not saved immediately when they’re called. For example, drop this piece of code anywhere in a plugin/theme:

        $example = get_option( 'an_example_option', 'an_example_default_value' );

        Load any page on the site. Then, check if the option is saved to your database in the wp_options table. It won’t be. WordPress won’t save this by default. It’ll only be saved when a user explicitly uses a feature (e.g., settings page, customizer) to save it.

        What we had before was that theme authors were saving defaults to the database so that theme options would work without the user visiting the customizer/settings-screen. The intention was very good, but the method was incorrect. Chip’s post is about using the correct method.

        And, there are a lot of real-world scenarios where saving to the database by default screws things up or won’t even work at all.

    • kevinhaig 2:08 am on November 28, 2014 Permalink | Log in to Reply

      Yes I understand that they are not saved immediately, however if you change 1 item and then save, all the defaults for the other items are saved. So the only time merging defaults is important is on new installs with themes when the options have not been adjusted at all, and the settings_API options entry has not been created. At least that is what I’m seeing in the database.

      • kevinhaig 2:21 am on November 28, 2014 Permalink | Log in to Reply

        To explain further, I have a ‘default’ => ‘value’ to all my add_setting() statements and these defaults are saved. I am assuming the only way around that would be to put nothing in the default?

        • Justin Tadlock 4:19 am on November 28, 2014 Permalink | Log in to Reply

          Technically speaking, you only have a single option as far as WP is concerned. That single option can have many “options” if it is an array (i.e., options within an option). So, yes, the other defaults are saved once you save one in that scenario because it’s all considered one option.

          You are half correct though about when it is important. The other half of that is handling new defaults on theme update for users who have already saved settings.

    • cats_456 9:05 pm on December 9, 2014 Permalink | Log in to Reply

      I’m using this method for loading options and I have got a problem with the Customizer.
      1. If I load mods in the array on init hook to use them later, customizer refreshes all color settings back to the current state after using setting with ‘refresh’ transport (all changes made to color pickers disappear from visual view in customizer).
      2. If I load mods with get_theme_mods function customizer works like (1). If I change it to call to get_theme_mod function in cycle then it start working as intended:

      function theme_themeslug_get_options() {

      $defaults = theme_themeslug_get_defaults();
      foreach( $defaults as $key => $value ) {
      if( get_theme_mod( $key, -1 ) != -1 )
      $defaults[$key] = get_theme_mod( $key );
      }

      return $defaults;

      /* return wp_parse_args(
      get_theme_mods(),
      theme_themeslug_get_defaults()
      );
      */
      }

      So, now I load options in array twice and use get_theme_mod function to make Customizer refresh color settings … And it seems to work! Any ideas? This problem appears inside of the live preview only.

      • jashwant 3:26 pm on January 17, 2015 Permalink | Log in to Reply

        I guess, you are experiencing the same issue, I am experiencing. `get_theme_mods()` does not work because customizer uses the filter of `get_theme_mod()` to modify the values of options, but there’s no such filter in `get_theme_mods()`

    • jashwant 1:44 pm on January 17, 2015 Permalink | Log in to Reply

      Great article. I am not using the same structure in my theme.

      I am using `get_theme_mods()` and saving it in a variable, instead of calling `get_theme_mod()` for every option. I assume, this will definitely save a lot of db access.

      But, it is failing on customizer. When I change values from 1 of control, `get_theme_mods()` does not reflect that change.
      A little digging reveals that, `get_theme_mods()` does not have a filter, but `get_theme_mod()` has filter for each setting individually. When I looked further, I found that, this filter is being used by customizer to change the setting value, when I change something in 1 of the control.

      How can I avoid `get_theme_mod`, and use `get_theme_mods()` and still reflect the changes of customizer ?

      p.s. `get_theme_mod` does a db access on each call. Right ?

      • Justin Tadlock 6:37 pm on January 25, 2015 Permalink | Log in to Reply

        I’d actually argue that assigning the result of get_theme_mods() to a global is bad dev practice. The reason for this is that doing so bypasses the theme_mod_{$mod} core hook. This means that plugins, themes, and even WordPress might not perform correctly. Basically, don’t do it.

        Use the core functions instead of unnecessarily building something on top of that.

        As far as hitting the database, that’s not an issue. WordPress is going to auto-load those options when the page is loaded and cache them. Calling get_theme_mod() is going to do nothing more than grab the cached data.

  • Chip Bennett 2:43 pm on July 1, 2011 Permalink
    Tags: , , Settings API   

    WordPress 3.2: Fixing the edit_theme_options/manage_options bug 

    Theme Developers:

    Many of you are aware of a minor bug in the Settings API implementation for Themes, in which add_theme_page() is passed the “edit_theme_options” capability, but the settings form submission via options.php requires the “manage_options” capability, resulting in users with the Editor role having access to the settings page, but being unable to submit the settings page form.

    Fortunately, WordPress 3.2 adds a new filter that can be used to resolve this issue: option_page_capability_{option_page}, where {option_page} is the name of the option page, as defined in the fourth parameter passed to add_theme_page().

    To get an idea of how to implement the fix, refer to the patch for the filter, which also includes an implemented fix for TwentyEleven. The key is to ensure that the capability passed to the hook is the same as the capability passed to add_theme_page.

    Here’s one example of how to implement:

    First, create a function to return the “edit_theme_options”:

    function themeslug_get_options_page_cap() {
        return 'edit_theme_options';
    }

    Then, hook the function:

    add_filter( 'option_page_capability_themeslug-options', 'themeslug_get_options_page_cap' );

    Then, ensure consistency with the add_theme_page() call. Notice that I replace the hard-coded string with the previously defined function:

    add_theme_page(
        'Theme Name Options',
        'Theme Name Options',
        themeslug_get_options_page_cap(),
        'themeslug-options',
        'themeslug_callback_function'
    );

    If you’re already testing against the 3.2 Release Candidate (and you are, aren’t you?), you should now be able to save Theme settings as a user with the Editor role.

     
    • Carl 9:44 am on October 27, 2011 Permalink

      The variable {option_page} in the filter option_page_capability_{option_page} should not be the fourth parameter from the add_theme_page call.

      Rather, it must be the same as the intended settings group that is to be modified. Clarification: the first parameter when doing register_setting(‘settings-group’, ‘setting’);

      For many these are set alike but that might not always be the case.

  • Chip Bennett 7:50 pm on January 5, 2011 Permalink
    Tags: Settings API,   

    Themes and the WP Settings API 

    The Settings API was initially introduced in WordPress 2.7, and is incredibly powerful. Part of its power is its automation of settings security (nonces, etc.), as well as automation of most of the admin options-page generation. Thus, use of the Settings API helps ensure more robust data security and more consistent user experience.

    Unfortunately, it doesn’t seem to have met with much widespread adoption in Theme development. Granted, very little documentation exists for proper implementation of the Settings API, and thus the learning curve is somewhat steep. To that end, Otto has an excellent tutorial, and Press Coders have a great write-up as well.

    I will be adding a Theme-centric Settings API tutorial to my to-do list. Given the increasing exposure to WordPress security issues – both real and perceived – I believe that, as we go forward, ensuring the robustness of data integrity and security of repository-hosted Themes will become increasingly important. Further, I believe that adoption of the Settings API will eventually prove to be requirement toward those ends.

    So, Theme Developers: have you tried to use the Settings API? What issues have you encountered? What difficulties do you envision in attempting to migrate your Themes’ current settings functionality to use of the Settings API? How long do you believe would be reasonable before the Theme Repository begins encouraging Theme developers to use the Settings API, either as a recommendation or as a requirement?

    Please note: this is an extremely early-stage discussion. At best, use of the Settings API might show up as recommended when the Guidelines are revised for WordPress 3.2. But, we want as much input as possible, as early as possible, so that we can begin addressing whatever concerns may exist.

    So, what are your thoughts?

     
    • Frumph 8:02 pm on January 5, 2011 Permalink

      Even though I do not currently use the settings API, purely for lack of knowledge of ‘how to’ implement with my already working and usable system with nonce’s and the like, that if it becomes a requirement that I would have to spend a countless amount of hours redoing quite a robust system of options.

      That doesn’t mean that I’m not in favor of moving everything to internal core coding. I am only considering the time involved for the infrastructure change. While it still being a huge undertaking I would rather go with it with complete knowledge on how to implement utilizing a like method with the tabbing and updating of separate options instead of every option, then how to utilize that information after the fact, while those tutorials are decent they are not all encompassing and I believe more work needs to be done with education on their part.

      • Chip Bennett 8:12 pm on January 5, 2011 Permalink

        Absolutely, Phil! Having stumbled through the process once on my own, I fully appreciate the difficulty of the learning curve.

        I want to start with a basic, start-to-finish, Theme-specific tutorial for implementing the Settings API, and then see what kinds of questions remain. Once developers get comfortable with the basics of implementation, then we can move on to advanced topics like the ones you bring up (and that I’m sure others will bring up, also).

        I envision this process taking a considerable amount of time – which is why I want to begin as early as possible, before even thinking about considering adding the Settings API to the guidelines in any fashion whatsoever.

      • Otto 8:55 pm on January 6, 2011 Permalink

        I wouldn’t say to make it “required” anytime soon, but implementing options pages (in themes or in plugins) is fraught with hard-to-spot security hazards that the Settings API makes a whole lot easier to cope with. So I’d say it’s one of those things that is best accomplished through proper tutorials and encouragement.

        “Recommended” is a definite though.

    • Edward Caissie 8:28 pm on January 5, 2011 Permalink

      I agree with the potential for the Settings API to become a recommended item in the Theme Review guidelines with the release of WordPress 3.2; but, a great deal of discussion must take place before it even reaches a point of being truly considered for that milestone. This is a great place to start.

    • Justin Tadlock 9:19 pm on January 5, 2011 Permalink

      I’ve already got half a tutorial written on using the Settings API, which is geared specifically toward theme developers.

      I see no issue in not using it if a theme developer uses the correct capability checks (edit_theme_options), uses nonces, properly validates/sanitizes the data, and escapes it on output within form elements. The Settings API actually makes much of this easier and definitely makes it cleaner.

      There’s also the *_theme_mod() functions a theme may use.

      Some complaints I hear from theme devs is that they can’t do tabs or other fancy stuff with the Settings API, which is entirely untrue. Of course, I’m asked how to do it. My reply is always that they should learn the basics before trying to add more complex functionality. I take the learn to crawl before you walk approach here.

      Our biggest concern should be about security. This comes down to a few things:

      Data validation.
      Proper capability checks when adding theme options pages. I’m involved in a few sites where a theme not using edit_theme_options would open up a settings screen to users that shouldn’t have permission to theme options at all.
      Properly escaping data on output using the esc_*() functions WordPress provides. An errant piece of HTML can break a theme settings page entirely and even be used for more malicious things if the data wasn’t validated before saving.

      The use of the Settings API should be recommended but not required. The requirement should be that a theme take proper steps to make sure there are no security issues. This should also be accompanied by relevant links to data validation and any other related links in the Codex.

      • Chip Bennett 9:41 pm on January 5, 2011 Permalink

        I’m of several minds here…

        On one hand, the primary concern at this point is encouraging adoption of the Settings API by Theme Developers, which will require massive amounts of education.

        On another hand, the Guidelines also say that if functionality is included, it must implement/support core functionality . Couldn’t that requirement be extrapolated to include Theme settings and data validation? If so, then we’re right back to use of the Settings API.

        And on yet another hand, I see no reason not to hold repository-hosted Themes to a higher standard with respect to the Settings API. Sure, Theme Devs can accomplish all the same things by hard-coding everything encompassed by the API; but if we want to remake the reputation of the Theme Repository, it would be in everyone’s best interest to move repository-hosted Themes to standardize on use of the Settings API.

        Not to worry, though; if use of the Settings API appears in the guidelines, it will remain only as suggested for a VERY long time.

        • Justin Tadlock 10:41 pm on January 5, 2011 Permalink

          There are several ways to implement/support core functionality: Use the regualar *_option() functions, use the *_theme_mod() functions, or use the Settings API.

          I’m all for setting a standard with using the Settings API and sticking with it though. I like the idea of eventually strongly recommending the use of the Settings API. Over time, we could check themes not using it on a case-by-case basis.

          I’d rather see something up on the theme review guidelines sooner rather than later though, even if just a small addition of text that theme settings pages will be checked for security issues and a link to the Settings API page in the Codex.

          Whether adopting the Settings API or not, this is an area that will require massive amounts of education. Nearly every theme I’ve looked at with a theme settings page has major issues. Most theme developers simply don’t know the first thing about properly creating a settings page. They’re using some generic script they’ve copied from a blog or another theme that just doesn’t cut it. One of the reasons I haven’t finished my tutorial yet is because there’s so much ground to cover and to put into a single tutorial.

          I’m also volunteering myself to check any theme settings pages for other reviewers that aren’t familiar with it enough. So, anyone can feel free to shoot me an email if they want me to look this over.

          • Chip Bennett 10:50 pm on January 5, 2011 Permalink

            I think we’re on the same page. Education is key (and I’ve got just about as much to learn as everyone else), and is what I think needs to be our primary focus for the foreseeable future.

            As for the current guidelines: any improvements you can make to the wording of the section regarding security, please feel free! We need to ensure that we at least have a link to the Settings API Codex page, if nothing else.

          • Edward Caissie 12:59 am on January 6, 2011 Permalink

            I’m all for this:

            I’d rather see something up on the theme review guidelines sooner rather than later though, even if just a small addition of text that theme settings pages will be checked for security issues and a link to the Settings API page in the Codex.

            Feel free to add some draft text at the appropriate places (here and the Codex).

    • Andrew Nacin 3:44 am on January 6, 2011 Permalink

      I’m strongly for the Settings API here. I’m also for a single option per theme, saved as an array and properly sanitized with a sanitization callback. I’m for edit_theme_options, despite the Settings API only supporting manage_options currently. I’m for secure themes. I’m for education.

      That said, there are areas where we can improve on this on core. Here’s a quick list I can refer to later: I already mentioned edit_theme_options/manage_options. Justin mentioned the theme_mods API, which would be powerful when combined with the Settings API. An array of options should be easier to do in the Settings API, perhaps. Themes need activation, deactivation, and uninstall hooks.

      Let’s see how much of that we’ll be able to do in 3.2. If you’re aiming for 3.2 as a guideline, that gives us some time to make the API more mature for theme pages. We also plan to re-do the settings screens in 3.2 (possibly), so this (possibly) is a good time to move forward.

      • Edward Caissie 8:14 pm on January 6, 2011 Permalink

        WP 3.2 is the ideal implementation of this addition to the guidelines and why we wanted to start this and other discussions now.

      • Ken Newman 10:11 pm on March 28, 2011 Permalink

        +1

    • Devin Price 6:17 am on January 6, 2011 Permalink

      The work Ptah Dunbar has done in WP-Framework beta is really impressive. With three lines of code you can set up an options panel and an option:

      add_theme_support( ‘theme-options’ );
      wpf_register_metabox( ‘options’, ‘general’, __( ‘General Settings’, t() ) );
      wpf_register_option( ‘general’, ‘textbox’, array( ‘type’ => ‘textbox’, ‘label’ => __( ‘This is a sample textbox’, t() ) ) );

      I’m sure any theme developer could handle that much. It would be lovely if something like that got tried out in plugin territory or eventually brought into core (which would standardize option controls and styles across the board).

      I’m also looking forward to a Tadlock tutorial- that tends to make everything much easier.

    • pross 9:07 pm on January 6, 2011 Permalink

      I’m all for making it ‘Required’ for 3.2 and recommended as soon as possible seeing as there is a flurry of settings API blog posts this last few days.
      I really hope the those activation/deactivation hooks become part of 3.2.

      @Nacin I just converted my theme over and its working fine with edit_theme_options (latest trunk)

    • Bruce Wampler 5:40 pm on January 10, 2011 Permalink

      First, although the concept of a settings API is sound, it certainly was not anything I was aware of when I started my own theme development. For me to ever switch to it now would literally take at least 40 or 50 hours of my time, and would result in no visible improvement for the user interface. If I were ever required to switch, I would be forced to abandon my theme. Thus, my first recommendation is that any future requirement grandfather in existing themes, especially ones that do use nonce for settings.

      Second is the sanitizing. One of the major features of my theme is the ability of the site admin to add real code – CSS, HTML, JavaScript, even PHP – to their site. None of the existing sanitizing functions currently in WP work right when allowing such low level flexibility. So given that a large number of WP users really want to do that, that capability – letting almost anything through – must be taken into consideration when the term “sanitizer” is used. I think a sanitizer with different levels – both of the admin logged on, and code level – might be useful.

      I do find it interesting that the existing text widget available for everyone to use has essentially no filtering on it at all – I assume because so many people uses it to add scripts from various external sites – at least that is how I read the source code for that widget. This does leave me a bit puzzled at all the discussion about sanitizing admin inputs from a theme options panel.

      And finally, a theme admin framework would be great, to be sure. Many themes have just a few, basic options, and being able to implement them in just a few lines of code would be great. On the other hand, some themes (which include many of the currently most popular themes) have hundreds of settings, and likely need total flexibility in designing the admin option interface. That is one thing I certainly would not like to give up. I’ve spent a huge effort producing what I think is a very easy to use interface, and I wouldn’t want to be constrained by a requirement to use some standard framework or interface.

      I agree Andrew’s comment above of a single option per theme (which I interpret to mean a single entry in the database per theme – although one might not be enough – my design likes having 3). But having a database call per setting is just far too inefficient, and difficult to uninstall.

      And finally, while it is important to ensure security, it is also important to allow some free rein on creativity. While some themes are being developed by experienced programmers, many are being developed by hobbyists and graphic designers. It would be shame to lose all that creativity by imposing an overly strict set of requirements for theme development. While it may have been overly free before your group was started, I hope the pendulum doesn’t swing too far back.

      Perhaps there could be a level of certification for themes –
      1. Secure – theme uses WP security API
      2. Likely Secure – theme uses WP security measures
      3. Admin Level Security – only admins can use theme admin panels
      4. Security Unknown – use at your own risk – theme not known to use WP security measures

      or something like that. That would be far more useful than eventually forcing all theme developers to use a specific settings API or framework.

      • Chip Bennett 8:24 pm on January 10, 2011 Permalink

        Bruce,

        You bring up great points, and your comment epitomizes the reason that we’re having a very early discussion on the topic before we make any changes.

        I’m curious why your “design likes having 3″ database options arrays? Why not a single, flat array with all options? If necessary, why not an array of 3 arrays?

        While I agree that the issue of complex user data input will need to be handled appropriately, I disagree that implementation of the Settings API in any way stifles creativity – especially for the hobbyist/graphic-designer-developed Themes, who are considerably less likely than developers more intimately involved with WordPress code to have a good grasp on proper data handling for Theme options pages. (Note that, for Themes without any options, the Settings API doesn’t even come into play.)

        While there may be a place for rating/ranking the security measures of each Theme, and while such information may be useful to end users, I see it as representative of considerably more work for the people tasked with reviewing Themes. As for your specific certification levels:

        1) Secure – Theme uses WP (Settings) API: this is where we want all Themes with options to be
        2) Likely Secure – Theme uses WP security measures: I’m not really sure what this means. IMO, “WP security measures” is equivalent to “WP Settings API”.
        3) Admin Level Security – only admins can use Theme admin panels: all Themes with options should meet this standard. The call to the settings page includes a capability argument for good reason.
        4) Security Unknown – once we implement Guidelines regarding data security, I don’t see any Themes that fall into this category passing the review process.

        The biggest concern I’m hearing so far is from Theme Developers who have already developed elaborate Theme settings pages, and are dubious about the feasibility, need, or benefit of switching to use of the Settings API.

        First, our primary focus, at least to start, will be the Themes that don’t properly implement data security in their settings pages (e.g. Themes that use copy-pasta from who-knows-how-many years ago).

        Second, the Settings API does not preclude any particular layout or design of Theme settings pages.

        Third, part of the philosophy of the WordPress project is to have a consistent UI/UX throughout the application. So, I see it as a benefit to end users to ensure that Theme settings page UI is consistent with the rest of WordPress.

        Fourth, our major emphasis, long before any Guidelines changes are made, will be education – both with respect to basic implementation of the Settings API, and with respect to implementation of the Settings API for more advanced uses and settings page layouts. We have no intention of creating any Guidelines that would be difficult or impossible to be met by the best-of-the-best Themes (the ones more likely to have advanced options and settings pages).

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel