New Project: Rewriting the requirements

Project description


Making the requirements clear, easy to follow and easy to check.


This project will not be starting with a blank slate, but make the best of what we have.


In no particular order:

  • Review whether current requirements and recommendations are valid
  • Add new requirements when necessary
  • Reorganize requirements and topics
  • Rewrite requirements to make them easier to understand


Project format, mandate, timeline and meeting times

Suggested format

A smaller project group with a separate meeting time is preferred, that way the Theme Review Team can still hold the regular meetings on Tuesdays to discuss other topics.


The group should have a mandate to change the wording of the requirements and examples with some exceptions:

Project leads/key reviewers should have access to making changes to the actual documents.

Major changes like completely removing a requirement should still be brought up during a Theme Review meeting.

Suggested meeting times

Every other Thursday at 19:00 CET,  alternating with the automation project meeting.

The Theme Review shindigs on the first Saturday of each month could also be used for longer meetings.


The project would need to decide on partial goals, for example monthly or bi monthly milestones to ensure that the project moves forward.


  • March 4 shindig: Requirements that have been voted on but not added,  should be added to the current requirements page.
  • In june, all requirements that are checked by the new Theme Check plugin should be separated from the rest of the requirements.


Our first meeting will be on Thursday, February 23 at 19:00 CET.


  • Introduction
    • Let’s see who are interested in helping out.
  • How can we work on the requirements together?
    • How do we record and share our work in progress? Do we need any external tools?
    • Decide who our target audience is to be able to set a “tone” of our content and level of difficulty for the examples.
    • In what format do we present the requirements, keeping time limits and milestones in mind?
  • Decide priorities for march-april
    • Missing requirements (band-aids)
    • Reordering and regrouping current requirements

March 4 Shindig

Requirements that have been voted on but not added should be added to the current requirements page.

Our second meeting will be on Thursday, March 9 at 19:00 CET.


  • Continue discussing any previous topics that were not finished during the last meeting.
  • Reordering and regrouping requirements
    • Is the requirement under the correct topic or does it need to be moved or placed under a new topic? We also have topics with only a few requirements that perhaps could be combined into one, like Naming and Screenshot.
    • Are there recommendations that should be moved to the required list? For example the Theme and Author URI.


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.


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() ), 

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( 

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() ), 
    // Theme Mods API:
    return wp_parse_args( 

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.

#guidelines, #sane-defaults, #settings-api, #theme-mods-api

How To Ensure Your Ticket Passes Final Approval Audit

Over the past couple of months, the number of approved tickets that have been reopened due to issues found during final-approval audit has declined, but many still get reopened. As a team, we want to ensure that tickets get approved (so that new Themes get added to the directory, and into the hands of end users), and we want reviewers to be able to take advantage of the incentive program.

So I want to step through the things I check when performing a final review audit. We’re looking for some high-level and/or high-impact things that would cause problems for end users:

Overall File Structure

  • Does the Theme look like it is derived from a common Theme (Underscores, Twenty Ten-Fourteen, etc.)? Are there included functional files that I’ll need to check. Are there asset folders (fonts, scripts, etc.) that I’ll need to check?


  • Check ThemeURI and AuthorURI. Are they appropriate?
  • If ThemeURI or AuthorURI reference commercial Themes, are those Themes sold as GPL-compatible?
  • If the Theme appears to be derived, does it include a proper derivative-work copyright/license attribution?


  • If the Theme has bundled resources/assets, are they listed in the readme with copyright/license attribution, or will I need to check file headers?
  • Is license for all bundled resources GPL or GPL-compatible?


  • Are Theme options properly escaped on output?
  • Is favicon, if used, disabled by default?
  • Does the TITLE tag include anything other than the call to wp_title()?
  • Does wp_nav_menu() reference theme_location, and not menu?
  • Are any stylesheet or script links output instead of being properly enqueued


  • Does the Theme only use one credit link? Is that credit link exactly ThemeURI or AuthorURI, with no SEO-seeding of link text, title attribute, etc.?
  • Are any footer scripts output instead of being enqueued properly?


  • Does template markup look generally appropriate?

Front/Home Page Templates

  • Does the Theme have front-page.php? If so, is it used properly? Does it account for both a static page and the blog posts index as site front page?
  • Does the Theme have home.php? If so, is it used properly as the default blog posts index template?
  • Does the Theme have any custom page templates intended to be used as either front-page.php or home.php?


  • Does the Theme properly output wp_list_comments() for the comments list?
  • Does the Theme properly output comment_form() for the comment reply form, rather than hard-coding the form?


  • Does the page template properly call comments_template()?


  • Are all functions and other things in the public namespace properly prefixed?
  • Is all functional output properly wrapped in callbacks and hooked into appropriate actions?
  • Is any of the functionality Plugin territory?
  • Does any of the functionality replicate core functionality?
  • Does the Theme use Theme options? Are they handled properly (single DB entry, proper settings page, sanitized on input, etc.)?
  • Do any of the Theme options replicate core options?

This list comprises 99% of what I look for in an audit, and accounts for the vast majority of issues encountered that require reopening tickets. So, if you verify these things before resolving the ticket as “approved”, the chances that your ticket will get reopened will go down considerably.

(Note: @emiluzelac may have other things to add to the list, for things he checks during an audit.)

#guidelines, #review-incentive, #review-process

Discussion: Theme Activation Standards

Currently, we are proposing a change to the Guidelines that would blanket-prohibit Themes from adding admin notices, redirects, or other similar functionality on Theme activation. The intent of the Guideline is to curtail the proliferation of nuisance/obtrusive Theme marketing in the user’s Admin.

In the vast majority of cases, such activation functionality should not be needed. Themes are required to use add_theme_page() to add a Settings page, which ensures that end users can always find the Theme’s settings page under the Appearance admin menu. The new requirement for sane defaults will ensure that Themes will always work “out of the box”, at least at a baseline (i.e. no-broken-sites) level. The recommendation for Themes to hook settings into the Customizer will help ensure that end users can visually preview Theme settings changes via the core Customizer (Appearance -> Customize). And the Contextual Help API ensures that Theme developers can add as much rich-text setup/configuration detail as necessary.

That said, there is still room for appropriate, standardized admin interventions on Theme activation. If we can agree on a consensus for standard admin interventions, then the Guidelines could reflect that consensus, and reviewers would have an objective standard to use when reviewing Themes.

So, let’s discuss. What’s appropriate? What isn’t? How can we define appropriateness objectively?


WordPress 3.9 Guidelines Revision Proposal: Round 2

Based on the previous discussion, the Guidelines proposal has been revised as follows. The proposed guideline change for Credit Links has been removed, and a proposed guideline change for Custom Logos has been added. Other proposals have been clarified based on previous discussion.

The two most significant clarifications regard arbitrary header/footer scripts, and Theme activation.

The proposed Recommended guidelines have not changed. While we understand the argument that there may not be consensus around certain implementations of features, we maintain that it is within the overall scope and objective of the Theme Review Team to encourage, facilitate, and drive best-practice consensus, and that it is in the best interest of end users to establish best-practice consensus. Thus, arguing that the Theme Review Team should not be establishing/promoting such best-practice standards in order to encourage consensus is moot – though we absolutely encourage discussion regarding what implementations should be considered/promoted as best-practice standards.

Other Discussion Topics


I would be interested in discussing our screenshot requirements. It seems that “reasonable facsimile”, as a standard, isn’t really sufficiently meeting anyone’s needs. While the intent was to avoid blatant marketing via screenshot, the requirement tends to be taken so literally that developers cannot even display user-configurable features in their screenshot. This is especially limiting for Themes with featured-content front-page templates. As currently interpreted, the “reasonable facsimile” standard prevents the screenshot from displaying the featured-content front-page, because the featured content first has to be configured. So, let’s discuss a more sane/useful guideline for screenshots.


I would also be interested in discussing the establishment of at least some “best practice” guidelines for translation-readiness – primarily, proper i18n of strings. I think it is all but a given that, eventually, we should be requiring Themes to be translation-ready; but currently we don’t have objective standards to follow. The first step, then, is creating those standards, and then educating developers on them.


Sane Defaults: Themes are required to use sane defaults.

Themes must not save default settings to the database without explicit user action, and Themes must function properly out-of-the-box without user configuration (that is: if the user does not save settings, the Theme will still function properly)

Bundled Plugins: Themes must not bundle Plugins.

Themes may incorporate support for Plugins, and may integrate Plugin code directly into the Theme (if that Plugin code meets the presentation-vs-functionality requirement), but Themes must not bundle Plugins as a whole.

Arbitrary Header/Footer Scripts: Themes must not provide Theme options for arbitrary header/footer scripts.

Arbitrary scripts are non-Theme-specific scripts added to the document head or footer to provide non-Theme-specific functionality. Such scripts are Plugin territory, and pose a significant security risk if not handled properly.

Custom CSS is acceptable, if properly sanitized.

Note: this guideline does not apply to content “scripts” added to the template outside of the document head/footer, such as script widgets (Google Maps, Twitter Feed, etc.). Essentially, if a script can be hooked into the template via wp_head() or wp_footer(), then it falls under this guideline; otherwise, it does not.

Theme Activation: Themes must not implement activation redirects, admin notices, or similar functionality on activation.

Note: this guideline does not apply to admin notices such as TGM recommended Plugins (if implemented properly). I will open a separate discussion regarding consensus/standard “unboxing” admin notices. The purpose of this Guideline is to curtail the proliferation of unnecessary/obtrusive marketing in the user admin area, not to prevent legitimate, useful activation information for the end user.

Theme Documentation: Themes must place any required documentation in a clearly marked readme file.

Note: this guideline applies only to required documentation. Required documentation includes copyright/license attributions, Theme design constraints/limitations, description of non-standard Theme functionality, etc. Plugin-standard readme.txt is preferred, but not required.

License: Themes are required to document in the Theme readme or license file the copyright/license attribution for all bundled resources.

Themes are required to provide this documentation in the Theme readme file, regardless of where or how those bundled resources provide their own attribution. The purpose is to ensure that end users (and also, reviewers) don’t have to search for this important information, and to ensure that the developer has done due diligence to ensure that licenses for all bundled resources are GPL-compatible.

Note: “blanket” statements for developer-owned resources (images, etc.) bundled with the Theme are perfectly acceptable. It is only third-party bundled resources that need to be listed explicitly.

Custom Logos: If implemented, custom logos must be user-configurable, and disabled by default.

This guideline will bring the handling of Theme options for custom logos in-line with the handling of Favicons. Currently, we require that “default” logos be generic/unbranded, but generic/unbranded logos are of no benefit to the end user. Likewise, Theme-branded logos are of no benefit to the end user. The most logical approach, then, is to require that custom logos not be displayed at all, unless the end user has configured one.


Theme Documentation

Themes are recommended to include a Plugin-standard readme.txt file.

Themes are recommended to meet the WP core standard for inline documentation.


Themes are recommended to be translation-ready.

Social Profile Links

Themes are recommended to use a custom navigation menu when incorporating social network profile links

Theme Options

Themes are recommended to integrate Theme options into the core Theme Customizer


Please discuss in the comments below.  If you have any additions to propose, please post them in the comments below, as well.