How to do a review (Draft)

Alert: DRAFT: This page is still a draft and being actively written.
HELP WANTED: If you want to help improve this page, contact @poena via SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/.. Last update: November 29 2018

Warning: This page is opinionated. It should not be used in place of the requirements page.  

What we expect of themes submitted to WordPress.org What we expect of themes submitted to WordPress.org

The theme must:

  • be GPL compatible.
  • be secure.
  • be free of PHP or JS notices.
  • not be in conflict with plugins e.g. prefixing.
  • be translation ready.
  • use WordPress functions, hooks, filters and libraries.
  • not do anything illegal, dishonest, or morally offensive.

Top ↑

Preparations Preparations

This assumes that you have a testing environment set up.  If you haven’t already, please read our related handbook pages: Become a reviewer, Theme review process and Working with Trac.

Note that you need to be able to switch between PHP 7 and 5.

Install the WPThemeReview standard for PHP Codesniffer.  This is a tool that checks PHP, JavaScript and CSS files against the requirements.

If you have never used PHP Codesniffer before, we encourage you to read the available documentation. It can seem complicated at first, but it is a very helpful tool that is well worth the time to learn, and we strongly recommend it.

You can use the PHP Codesniffer both as a command line tool, or together with your code editor.

PHP_CodeSniffer wiki
WPThemeReview introduction

There are several plugins that can help you with the review, but you will also need to check all the files manually (yes that is correct: all the files).

You will need access to the requirements page, the developer code reference and the theme developer handbook.

Tip: If you need help with the review, you can ask other reviewers in the #themereview Slack channel.

Top ↑

Performing the review Performing the review

We want to encourage you to find a flow that works fastest for you. You might find it easiest to work through the list of requirements, or you might find it easier to look at file by file. Since most themes follow a standard, so can your review.

Please remember that we do not review design, but we review usability. We only require design changes if something is broken or unusable. You may add design recommendations to the review, but it is optional.

The focus of the review should be security and license. You may need to test the theme settings but you should only need to spend a couple of minutes on each.

When writing the review, separate requirements from recommendations. This makes it easier for the author to make required changes, and for other reviewers to do follow up reviews.

The most common files to find errors in are:

  • style.css and readme.txt Missing license information or using the wrong links.
  • header.php Hard coding scripts, styles and charset. Text missing translation functions.
  • footer.php Hard coding scripts. Options such as copyright texts that are not safely escaped on output.
  • functions.php Functions that are missing prefixes, functions that do things that we consider plugin territory.
  • customizer.php Settings that are missing sanitizing. Text missing translation functions.

We recommend starting with these files, then running the plugins and finally activating the theme and viewing the different pages and settings.

How to use the results of the Theme Check and Theme Sniffer scans:

  • Errors needs to be fixed before a theme can be approved.
  • Warnings, info, and notices are indications of something that needs to be manually checked.
  • Recommended Recommendations are not required to be fixed before a theme can be approved.

You may include the error report in your review.

By searching for specific phrases you can drastically reduce how long a review takes. There are tools available that can search zip files, such as grep. Editors like PHPStorm, Atom and Sublime Text also lets you search the entire theme folder.

Look for these boxes throughout this page for tips:

Tutorial: Search for…

Tip: tip…

Top ↑

1. License 1. License

WordPress themes are derivative of WordPress because they require WordPress code to function. Themes inherits the license that WordPress uses: GNU General Public License v2, or later.

That is why themes must be compatible with the GNU General Public License v2, or any later version, to be hosted on WordPress.org.

Warning: This is a blocker. If the theme is not compatible, you can stop the review and let the author know that you can’t continue the review until the licensing issues are resolved.

Here you will find general information about GPL, including a list of compatible licenses. The Theme Developer Handbook also has a chapter on Licensing.

In 2009, Matt Mullenweg confirmed again that while GPL only requires the PHP code to be compatible, WordPress.org will only host and promote themes that are 100% compatible with GPL. 

This means that all code, fonts and images and any other resources that are used by the theme, must be compatible with GPL. 

-The Theme Review Team does not have a mandate to change or make exceptions to this requirement, and it means that reviewers need to check both the submitted theme, and make sure that the theme author does not promote themes that are not compatible.

Checking the license of the submitted theme Checking the license of the submitted theme

For the reviewer to be able to confirm that the submitted theme is compatible, authors need to include license and copyright for the theme itself, and a list of all resources used in the theme.

Themes are required to include the license in the header of the style.css file.
Open style.css and make sure that these lines are in the header and that they are not blank.
Examples:

License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
License: GNU General Public License v2 or later
License URI: LICENSE

Where license.txt is included and contains a copy of the license.

The remaining license and copyright information should be included in the readme.txt file or in the license.txt file.

Make sure that the author has included a copyright notice for the theme.
Example:

Twenty Seventeen WordPress Theme, Copyright 2016 WordPress.org

Themes need to include license and copyright information for all assets including stylesheets, scripts, fonts and images (even images used in the screenshot and images that the author has created).

-It is not enough to only keep the information in the file header of the third party script, it would simply take too long to review, so we ask that authors write a list of all the assets.

Where possible, a link to the source should be included
Example:

normalize.css, Copyright 2012-2016 Nicolas Gallagher and Jonathan Neal
License: MIT Source: https://necolas.github.io/normalize.css/

If a theme incorporates code from other themes or plugins, these must also be attributed.
Example:

Theme name is based on Underscores http://underscores.me/,
(C) 2012-2017 Automattic, Inc.
License: GNU General Public License v2 or later

Validate the themes readme file with this tool.

Top ↑

Checking the license of other themes Checking the license of other themes

This step is cause for a lot of confusion and frustration for both theme authors and reviewers. 

The reason why reviewers need to know the license of the authors other themes, -themes that are not even submitted to the theme directory, is that WordPress.org may not be used to promote themes that are not 100% GPL compatible.

Authors who provide themes in other places than WordPress.org, -whether it is on their own website or a marketplace, need to show that all their themes are 100% compatible with GPL.

The easiest way for authors to do this, is to add license information to their website. This can be included for example in the footer, or in a terms of use page. That way, the reviewer can quickly find the information and can continue the review. 

The easiest way for reviewers to check this, is to visit the Author and Theme URI, and look for the information. 
If the author has added the information correctly, this step only takes a few seconds. If the information cannot be found, you can request the theme author to add it.

Terms of use can be difficult to read.  If you are not sure, you can always ask the theme author and other reviewers. Terms that limit the theme usage in a way that is not compatible with GPL is not allowed, for example:

  • Stating that the user cannot remove or edit a footer credit link.
  • Stating that the theme can only be used on one website.
  • Stating that the user is not allowed to sell or distribute the theme.

If the author or theme URI has links to marketplaces, follow the links and make sure that all themes sold from the authors account are 100% compatible with GPL.

Related requirements can be found here.

To illustrate this and to hopefully reduce some of this confusion, here are some examples:

Authors cannot submit a free theme, that is 100% GPL compatible, and use the traffic and the links in that theme, to sell a premium version of that theme, which is not 100% GPL compatible.

Authors can submit a free theme, that is 100% GPL compatible, and use the traffic and the links in that theme, to sell a premium version of that theme, which is also 100% GPL compatible.

Authors cannot submit a free theme, that is 100% GPL compatible, and use the traffic and the links in that theme, to give away or sell other themes they have created, which are not 100% GPL compatible.

Authors can submit a free theme, that is 100% GPL compatible, and use the traffic and the links in that theme, to give away or sell other themes they have created, which are also 100% GPL compatible.

It does not make a difference if a theme is sold or given away on the authors website, or on a different marketplace. Authors are allowed to sell themes on marketplaces as long as these themes are 100% GPL compatible, not sold under a split license or similar.

Authors are allowed to write blog posts, articles, and in other way present themes from other authors and theme shops, regardless of the themes license.

If the author sells themes on Theme Forest, we expect the license information to be included in the price and license information area:

If you need to ask an author who sells themes on Theme Forest to change their license information, this link explains the difference between the license options and how to change it: https://help.market.envato.com/hc/en-us/articles/202501194-Theme-Plugin-Licensing-Options

Changing the license may take some time. If the author has assured you that they are working on changing the license, please consider keeping their ticket open while you wait.

Top ↑

2. Security 2. Security

The theme needs to be as secure as possible. To be able to review this, you need a basic understanding of escaping, validating and sanitizing.

Please read and refer to the Theme Security chapter in the Theme Developer Handbook and the WordPress.com VIP security overview.

Note: All untrusted data should be escaped before output. Untrusted data includes user input, for example theme options.

A common mistake is echoing get_theme_mod(), get_option() or get_post_meta() without escaping.

A rough rule of thumb is that

  • When a WordPress function begins with “get_”, such functions generally need to be escaped.
  • When WordPress functions begin with “the_”, generally these are already escaped prior to output.

Examples
get_permalink() needs to be escaped with esc_url(): esc_url( get_permalink() )
While the link in the_permalink() is already escaped.

get_the_title() is not normally escaped since we want to allow html in titles.
To use a post title in a title attribute, the_title_attribute() should be used instead. This content is escaped.

In this example, the link to the image in header_image() is already escaped with esc_url(), but the width and height attributes need to be escaped.

<img src="<?php header_image(); ?>"
width="<?php echo esc_attr( get_custom_header()->width ); ?>"
height="<?php echo esc_attr( get_custom_header()->height ); ?>" />

get_the_category_list() is an example of a commonly used function that starts with get_ that does not need to be escaped. The links to the categories in the function are already escaped with esc_url().

To determine if a WordPress function needs to be escaped, you can look it up in the developer reference.

You can also double check content inside html attributes. A common mistake in themes is forgetting to escape the placeholders for the comment- and search forms.

Example:
placeholder="Search..." would need to be both escaped and translation ready:
placeholder="<?php esc_attr_e( 'Search...', 'textdomain' ); ?>"

Tutorial: Search for:
echo get_, echo $
href=, source=, placeholder=, value=, alt=, title=, name=

See a list of all html attributes

Note: Validate and/or sanitize untrusted data before entering into the database.

There are basically 3 places where we allow user input to be saved: the Customizer, in meta fields, and in custom widgets. Separate option pages are no longer allowed.

Top ↑

The customizer The customizer

Look for the customizer file(s) and make sure that all options are sanitized and/or validated using the correct functions and methods. All settings in the customizer needs a sanitize_callback or sanitize_js_callback.

Common mistakes include:

Another problem is when a custom function is added as a sanitize_callback, but the value is returned without being sanitized.

Tutorial: Search for:

  • $wp_customize->add_setting
  • sanitize_

Customizer settings with checkboxes, radio buttons, multiple options (select and choice) and settings that require a specific format (for example numbers only) should be validated before saving.

Tip: The Theme Review Team has a managed GitHubGitHub GitHub is a website that offers online implementation of git repositories that can can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged be the repository owner. https://github.com/ repo which provides useful examples of various customizerCustomizer Tool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. features, including sanitization. This repo can be found here.

Top ↑

Custom meta boxes Custom meta boxes

Theme authors are allowed to add custom fields for design related options to posts and pages. Non design related options are not allowed, nor is adding fields to other screens than posts and pages.

Tutorial: Search for:
add_meta_box

Submitting and saving the user input

  • Make sure that a nonce is used. wp_verify_nonce should be used rather than check_admin_referer(). See Using Nonces to learn more about nonces.
  • Make sure that a capability check is used; look for current_user_can() in combination with edit_pages or edit_posts respectively. Capabilities should be used rather than roles.
  • The data needs to be sanitized and or validated with the correct functions or methods before saving.
  • Post meta-data needs to be escaped on output, whether it is displayed in the admin or on the front.

The Plugin Developer Handbook has a chapter on managing Metadata and adding custom meta boxes.

Top ↑

Custom widgets Custom widgets

Theme authors are allowed to add custom widgets that uses existing content, but also widgets that create minor content.

Tutorial: Search for: WP_Widget

A custom widget can be very varied, but can have the same security issues as metaboxes.
The data needs to be sanitized and or validated with the correct functions or methods before saving. Widget data needs to be escaped on output, whether it is displayed in the admin or on the front.

Tip: Even options that are only available if a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party is installed needs to be secure.

Recommended reading
WordPress.com VIP Best practices: validating, sanitizing, escaping

Codex: Escaping: Securing Output

A guide to writing secure themes
Part 1 -introduction/
Part 2 -validation/
Part 3 -sanitization/
Part 4 -securing-post-meta/

Top ↑

3. Code 3. Code

Check the theme to make sure that there are no errors, warnings or notices.

  • After activating the theme, check for PHP notices, errors and warnings as well as JavaScript issues and missing files.
  • View archives, single post and pages. Perform a search and test the 404 page.
  • Add custom widgets, test them in both the admin and on the front.
  • Test custom page templates.

You do not need to validate HTML or CSS.

Top ↑

PHP version compatibility PHP version compatibility

Themes are required to support PHP7. This means there must be no PHP errors or notices when running on PHP7.
Themes are allowed to use newer PHP features that are not included in PHP 5.2 or PHP 5.5, but there must not be any PHP errors when the theme is installed on a site using a lower than supported PHP version, e.g. PHP 5.x.

The Theme Sniffer plugin allows you to select a minimum PHP version, and will print an error if a theme uses features not available in that version. In those cases, you should test the theme on both PHP versions.

Theme authors can choose whether or not to allow the theme to be activated on sites using a lower PHP version.

Top ↑

Admin pointers and private functions Admin pointers and private functions

Themes should not use features/APIs that are meant for WP Core use only. This is not very common, so you don’t need to memorize these functions; if you look them up in the developer reference, you will see that there is a notice at the top of the page, explaining that is is not intended to be used in themes or plugins.
List of admin pointers
List of private functions.

Tutorial:
Search for:
pointer