tutorials

Posts filed under tutorials

A Guide to Reviewing Themes for the WordPress Theme Repository

Filed in Web DevelopmentTags: Theme Review, Themes, tutorials, WordPress

Thanks in large part to Justin Tadlock's recent blog post, in which he solicited more people to get involved with the WordPress Theme Review Team (WPTRT), we have seen a fantastic, huge influx of new volunteers. Many of these new volunteers have had questions about how to perform a Theme review. Hopefully this guide will help answer those questions.

Getting Started

Test Environment Setup

First things first: review How to Join WPTRT.

WordPress Setup

Ensure that a few WordPress settings are modified in order to facilitate the Theme Unit Tests:

  • Settings -> General: set the Site Title to something fairly long, and set the Tagline to something even longer. These settings will facilitate testing how the Theme handles these values.
  • Settings -> Reading: set "Blog pages show at most" to 5. This setting will ensure that index/archive pagination is triggered.
  • Settings -> Discussion: enable Threaded Comments, at least 3 levels deep. This setting will facilitate testing of Theme comment list styling.
  • Settings -> Discussion: enable Break comments into pages, and set 5 comments per page. This setting will facilitate testing of Theme paginating link markup/styling.
  • Settings -> Media: ensure that no values are set for max width or height of Embedded media. This setting will facilitate testing of the Theme $content_width setting/implementation.
  • Settings -> Permalinks: ensure that a non-default permalink setting is selected, e.g. "Month and name". This setting will facilitate stepping through the Theme Unit Tests.

Next, create at least two Custom Menus:

  • Long Menu: all included Pages
  • Short Menu: a menu of 2-3 Pages

Now, you're ready to be assigned a ticket! Read on for the detailed review process.

Policy Requirements

The first area to review involves some policy requirements, rather than code quality. I verify these before I ever download or install the Theme, by reviewing the appropriate template files using the "SVN" link in the Trac ticket.

License

  • Review the header tags in style.css. Ensure that the License: and LicenseURI: header tags exist, that the indicated license is GPL-compatible, and that the indicated URI is a valid, full-text license.
  • Review the Theme files for bundled fonts or icon sets; if included, verify that the licenses for these bundled resources are GPL-compatible, and explicitly declared by the Theme, either in style.css, readme.txt, or somewhere similarly appropriate.
  • Review other template files, such as footer.php, to ensure that there are no inline comments regarding use restriction, such as prohibiting changing the footer, or requiring a credit link, etc.

Credit Links

  • Review the header tags in style.css. Ensure that Theme URI and Author URI, if used, are valid and appropriate.
  • Review the indicated URLs. Ensure that the sites are appropriate, that they do not sell or promote non-GPL WordPress Themes, and that any license or terms and conditions information does not include non-GPL-compatible content.
  • Review footer.php, sidebar.php, etc. and ensure that the Theme does not include any other inappropriate hard-coded links (sponsor links, SEO links, spam links, etc.). Ensure that all public-facing copyright notices indicate the site name, rather than the Theme name or developer.
  • Review functions.php and ensure that the Theme does not hook in any other inappropriate links or copyright notices.

Theme Name

  • Verify that the Theme name meets naming convention requirements.

Screenshot

  • Verify that screenshot.png is sized appropriately.

Theme Check

Next, install the Theme, and before activating, run Theme Check. Note any Warning or Required notices in the Trac ticket. (Note: for any Theme uploaded since late March 2011, Theme  Check should return no such notices, as they should all be caught by the Theme uploader script. If you notice any, please email the Theme-Reviewers mail list, and indicate what notices you observed.)

You are welcome to note Recommended or Info notices in the Trac ticket, but I generally don't. These notices are more for your reference, as you continue to review the Theme.

For Recommended notices regarding Theme functionality (Post Formats, Post Thumbnails, Navigation Menus, etc.), verify that the Theme does not use a custom implementation. If the Theme does use a custom implementation, note in the Trac ticket that the Theme is required to support the core implementation of the functionality.

Step through each Info notice, and review the Theme template files to determine if the notice is applicable. For example: verify appropriate use of include() vs. get_template_part(); verify appropriateness of hard-coded links; etc.

Code Quality

Now, the review enters the bulk of the requirements in the Theme Review guidelines.

header.php

Review header.php, and verify:

  • All appropriate document head guidelines (valid doctype declaration, properly formed tags (html, head, meta, etc.)
  • Feed links are not hard-coded into the document head
  • No CSS files other than style.css are hard-coded into the document head. (These files must either be enqueued and hooked in appropriately, or added using IE conditional tags.)
  • No scripts or script file links are hard-coded into the document head. (These must be enqueued and hooked in appropriately.)
  • No unnecessary meta tags (WordPress generator tag, SEO meta tags, copyright meta tags, etc.) are hard-coded into the document head.
  • The wp_head() template tag is placed immediately before the closing HTML head tag.

footer.php

Review footer.php, and verify:

  • No scripts or script file links are hard-coded into the footer. (These must be enqueued and hooked in appropriately.)
  • The wp_footer() template tag is placed immediately before the closing HTML body tag.

functions.php

Review functions.php, and verify:

  • All custom Theme functions, constants, classes, global variables, and options are prefixed with theme-slug (or an appropriate variant).
  • Theme Settings are implemented properly:
    • Theme options are added to the database via a single options array, rather than separately
    • Settings page added via add_theme_page() rather than add_menu_page()
    • Settings page capability is edit_theme_options, rather than admin, manage_options, edit_themes, etc.
    • All untrusted data are sanitized/validated upon input into the database, and escaped upon output
    • If the Theme is not using the Settings API:
      • Nonce-checking is performed explicitly
      • $_POST, $_GET, and $_REQUEST data are sanitized/validated upon input into the database, and escaped upon output
  • No core WordPress functions introduced prior to one previous, major WordPress release are wrapped in function_exists() conditionals.

style.css

Verify that all tags listed in the Tags: header tag are appropriate, and that all claimed functionality is included in the Theme.

Theme Template Files

Note which hierarchical template files are used (e.g. single.php, page.php, archive.php, date.php, author.php, category.php, tag.php, taxonomy.php, 404.php, home.php, front-page.php, and search.php), so that you will know which of these to verify when performing the Theme Unit Tests, later.

Review Theme template file names, and ensure that any hierarchical template file name variants (e.g. page-foo.php, category-foo.php, etc.) are included in the Theme documentation, with an explanation for their use.

File Includes

Review Theme template files, make note of any uses of include() or require() and ensure that such use is valid. Verify that:

  • All headers are included via get_header()
  • All footers are included via get_footer()
  • All comments templates are included via comments_template()
  • All sidebars are included using get_sidebar()
  • All template part files are included via get_template_part()
  • Any search form markup is included via get_search_form()
  • Any login form markup is included via wp_login_form()

Theme Unit Tests

Now the review moves on primarily to the requirements in the Theme Unit Tests.

Theme Activation Tests

  • Activate the Theme, and open the site in your browser. Verfiy that Debogger returns no PHP errors, warnings, or notices for index.php.
  • Via Dashboard -> Tools -> Deprecated Calls, verify that Log Deprecated Notices does not return any deprecated function calls or other notices.
    • Note: check the Deprecated Calls log one final time when you complete the review, after you switch back to your default Theme. Sometimes, some notices get thrown when the Theme is deactivated.
  • If the Theme includes a Custom Theme Settings:
    • Load the Settings page, and verify that Debogger returns no PHP errors, warnings, or notices.
    • Save current/default settings, and again verify that Debogger returns no PHP errors, warnings, or notices.
    • Test each Theme Option in turn, and verify that each option can be updated, that the setting is applied properly in the Theme, and that Debogger returns no PHP errors, warnings, or notices.
    • If the Theme Settings page includes a "Reset Defaults" button, reset defaults, and verify that default settings are applied, and that Debogger returns no PHP errors, warnings, or notices.
  • If the Theme supports Custom Image Headers, select a custom header, and verify that it is applied/displayed properly
  • If the Theme supports Custom Backgrounds, select a custom background image or color, and verify that it is applied/displayed properly
  • If the Theme supports Custom Nav Menus:
    • Verify that the default/fallback output renders properly
    • Apply the Short Menu to each theme_location, and verify that the menu renders properly
    • Apply the Long Menu to each theme_location, and verify that the menu renders properly, without breaking the site/menu layout
    • If the Theme has a limitation on number of list items in any theme_location, ensure that such limitation is documented in readme.txt
  • If the Theme adds Custom Widgets, verify that all custom Widgets function as intended, generate no PHP errors, are secure, etc.
  • If the Theme supports Custom Editor Style, verify that the Post editor content renders reasonably similar to the site output
  • If the Theme requires any custom settings or setup, ensure that setup instructions are documented in readme.txt

General Tests

Run the W3C HTML/CSS validator on the Readability Test post (to ensure minimal WordPress-caused validation errors), and note any egregious validation errors, such as:

  • Malformed or improperly closed tags, that cause the page layout to break
  • An exceptional number of HTML or CSS errors

View the site index page, and verify:

  • The screenshot, as seen in the Trac ticket, is a "reasonable facsimile" of the default view of the site
  • The Site Title and Tagline, if displayed, do not break the page layout

Template Page Tests

  • For all included template-hierarchy index pages (index.php, home.php, archive.php, date.php, author.php, category.php, tag.php), verify requirements, as specified.
  • If the Theme includes either a front-page.php or a home.php template file, go to Dashboard -> Settings -> Reading, and set the Front Page to display a Static Page (use any existing Page), and set the Blog Posts index to another Static Page (e.g. "Lorem Ipsum"). Verify requirements, as specified.
  • Trigger the Theme's 404.php page by navigating to a non-existent Page slug (e.g. www.domain.tld/sit-amet). Verify requirements, as specified.
  • Trigger the Theme's search.php page by performing a search (e.g. "lorem ipsum"). Verify requirements, as specified.

Blog Posts Index Page Tests

Return to the Blog Posts index page. Step through the Blog Posts Index Page tests.

Individual Unit Tests

Step through each Blog Post and Static Page, verifying all requirements, as specified. Each unit test should be fairly self-explanatory.

Finishing the Review

At this point, the review is thorough and complete. Summarize your comments in the Trac ticket and close the ticket with the appropriate resolution (or propose a suggested resolution, if you do not have appropriate rights to close the ticket).

Incorporating the Settings API in WordPress Themes

Filed in Web DevelopmentTags: Settings API, Themes, tutorials, WordPress

The inter-tubes are awash in tutorials for how to add Theme Options to WordPress Themes - so why write another? Primarily, because most such tutorials are several years old, don't implement current best-practices, and were written without any awareness of the WordPress Settings API.

While others such as Otto and Ozh have done yeomen's work in explaining how to implement the Settings API, I have not yet come across anything that really put everything together, and explained the process and implementation from beginning to end, in a way that even the less-experienced Theme developers (like me) could easily understand.

This tutorial will attempt to fill that gap, by providing examples of current (as of the pending release of WordPress 3.1) best-practice implementation, not merely of the Settings API, but of Theme Options implementation as a whole, including:

  • Registering options in the database as a single options array
  • Initializing default options
  • Creating a single Theme Settings page (with tabs)
  • Defining settings page sections and fields
  • Validating and white-listing user-input form data
  • Adding Settings Page contextual help
  • Enqueueing custom CSS for the Settings page
  • Implementing settings in the Theme template files
  • Enqueueing front-end CSS

Throughout this tutorial, I will be using code from my Oenology Theme for implementation examples. For full code, see the latest development version.

Assumptions: Best Practices

The following will be the working list of best practices that will be incorporated:

  • Theme Settings defined as an options array in a single database entry
  • Theme settings added to a single Theme Settings Page
  • Theme Settings page is added to the "Appearance" menu
  • Theme Settings page added using the "edit_theme_options" user capability
  • Theme Settings registered, updated, and validated using the WordPress Settings API
  • Theme Settings modify the template using action/filter hooks wherever possible

Getting Started

The first thing we need to do, even before touching any code, is to determine:

  • What options to include in the Theme
  • How to organize those options on the Theme Settings Page

In my case, I am adding only a handful of simple options:

  • Header Navigation Menu Position: currently, Oenology displays the Header Navigation Menu above the site title and description. I am adding a setting optionally to display the Header Navigation Menu below the site title and description.
  • Header Navigation Menu Depth: currently, Oenology is designed so that only the top-level Pages display in the Header Navigation Menu, and Child Pages display in a left-column sub-menu. I am adding a setting optionally to display Pages to a depth of one (top-level Pages only), two, or three, with hover drop-down menus.
  • Footer Credit Link: currently, Oenology does not display any form of footer credit link. I am adding a setting optionally to display a footer credit link.
  • Varietals: the default style of Oenology is intentionally minimal. It is intended to be clean, simple, and cross-browser. I am adding a setting optionally to select from among Theme "skins" (which, in keeping with the oenology metaphor, will be called "varietals"), which will apply different color/style schemes to the Theme.

Given that I'm only adding four Theme options, I could very easily put all four together on one Settings page. However, I may want to add additional options in the future - and also, I want to provide a proof-of-concept for creating complex Theme Settings pages in a way that supports the Settings API. So, the Theme Settings page will have two tabs: "General", and "Varietals". Further, the "General" tab will have two sections: "Header Options" and "Footer Options".

So, that's our basis. Let's get started!

Oenology: How To Create a Child Theme and a Custom Page Template

Filed in Web DevelopmentTags: Oenology, Themes, tutorials, WordPress

This tutorial will explain how to use the Child Theme concept to customize a WordPress Theme. Specifically, this tutorial will explain how to create a Child Theme to hold future-proof Theme customizations, and then will explain how to build a custom Page template within that Child Theme. This tutorial is based on the Oenology Theme.

A brief background: recently, a user of the Oenology Theme contacted me, asking how to create a custom Page template. Specifically, this user wanted to have content of a particular Page display in a single, wide column with no sidebars. This customization is quite easily implemented using a Child Theme, as I will explain.

Creating a Child Theme

The first step is to create a Child Theme.

In its simplest form, a Child Theme doesn't have to be anything more than a single file: style.css. While some Child Themes are much more complex, all start with this one file. WordPress will use two critical pieces of information from the Child Theme's style.css file to do all of the rest of the heavy lifting: a header tag and a file import.

Let me show you how easy it is. In your text editor of choice, paste the following into a blank file, and save it as "style.css":

/*
Theme Name: Oenology Example Child Theme
Description: Example Child Theme based on Oenology
Template: oenology
Version: 1.0
*/

/*
THIS MUST COME FIRST!
Inherit styles from oenology parent theme.
*/
@import url("../oenology/style.css");

Congratulations! You just created your first (fully functional) Child Theme!

Here's how it works.

First, this "header tag" tells WordPress that the Theme is a Child Theme, and to use all of the template files from the indicated Parent Theme, if they are not found in the Child Theme:

Template: oenology

In other words, if we don't add an "index.php" template file to our Child Theme, WordPress will use the "index.php" template file from Oenology.

Second, this file-import tells the style sheet to import all of the styles as defined in the Parent Theme, Oenology:

@import url("../oenology/style.css");

Due to the way that inheritance works with CSS, any styles we define in our stylesheet that come after this file-import call will supercede the styles defined in the Parent Theme. (Note: the exact nature of CSS rules regarding specificity are outside the scope of this tutorial.)

And that's it! That's all the information that must be provided for a working Child Theme.

Oenology Child Theme available to be activated

The Oenology Example Child Theme listed in the Themes section of the WordPress Admin area

At this point, you could simply FTP your newly created style.css file to \wp-content\themes\oenology-example-child-theme\, and you'll see your Child Theme appear under Themes in your WordPress admin.

You could activate your Child Theme at this point, and it would work (it would just look and act exactly the same as its Parent Theme, Oenology, at this point, because we've not yet added any customizations).

But, let's make our first customizations first.

Creating a Custom Page Template

Now the real fun begins! Let's create our custom Page template.

Oenology Page template fileStart by making a copy of the "page.php" template file from the Oenology Theme. Since the custom template we want to create is a wide, one-column page, we will name our copy "page-one-column-wide.php".

Important! At this point, we are done with the Oenology Theme. Be sure not to make any changes to the Oenology Theme template files. Likewise, do not save your Child Theme's "style.css" file or any other file in the Oenology Theme directory!

Save "page-one-column-wide.php" in the same directory where you saved "style.css", and then open it in your text editor of choice.

We will make three primary changes:

  1. Change the Template name.
  2. Add a custom class to the HTML <body> tag.
  3. Remove the two sidebars.

Changing the Template Name

Look for the following at the very top of the file:

/*
Template Name: Page
*/

This tag tells WordPress what this particular Template file is. Since we are creating a new, custom Template, we need to rename this tag. (Whatever we put here will be displayed in the Add Page screen, as we'll see later.) Change this tag to the following:

/*
Template Name: Page One-Column Wide
*/

Adding Custom Class to the HTML <body> tag

Next, look for the following code (immediately following the above code):

<body id="page" <?php body_class(); ?>>

Modify it as follows:

<body id="page" <?php body_class( 'page-one-column-wide' ); ?>>

This change tells WordPress to add the CSS class "page-one-column-wide" to the HTML <body> tag. We will use this CSS class to define our custom style for our template.

Removing The Sidebars

Finally, find and delete the following code, starting around Line 53:

<!-- Begin Left Column (div#leftcol) -->
<div id="leftcol">
<?php
/*
div#leftcol contains the left column content of the three-column layout.
*/
get_sidebar('left');
/*
sidebar-left.php is the left column content. Used in all primary template page types (index.php, single.php, archive.php, search.php, page.php)
For index.php, sidebar-left and sidebar-right both appear to the right of the main content column.
For page.php, sidebar-left is to the left, and sidebar-right is to the right, with the main content column in the center.
*/
?>
</div>
<!-- End Left Column (div#leftcol) -->
<!-- Begin Right Column (div#rightcol) -->
<div id="rightcol">
<?php
/*
div#rightcol contains the right column content of the three-column layout.
*/
get_sidebar('right');
/*
sidebar-right.php is the right column content. Used in all primary template page types (index.php, single.php, archive.php, search.php, page.php)
For index.php, sidebar-left and sidebar-right both appear to the right of the main content column.
For page.php, sidebar-left is to the left, and sidebar-right is to the right, with the main content column in the center.
*/
?>
</div>
<!-- End Right Column (div#rightcol) -->

Here, we simply remove the code that adds the Sidebars to the template, so that they do not display.

That's all we need to do with the template file. Save your changes, and we will move on to styling our new Page template.

Defining CSS for Custom Page Template

Once again, open "style.css" in your text editor of choice, and look for the following line:

@import url("../oenology/style.css");

Be sure to make all additions beneath this line. This rule is very important.

Beneath this line, add the following style definitions:

#page.page-one-column-wide #extent #main {
width: 1000px;
margin-left:0px;
}
#page.page-one-column-wide #extent #main img {
max-width: 990px;
width: auto;
height: auto;
}

The first rule changes the width and margin of the main content area, so that it takes up all the space made available by the removal of the sidebars. The second rule ensures that any pictures that are added to the content will take up the full available width.

At this point, we're done make edits to Theme template files. Now the fun begins: using our new Child Theme, and custom Page Template!

Using the Custom Page Template

Using whatever method you prefer, upload the two files, "style.css" and "page-one-column-wide.php" to the following directory:

\wp-content\themes\oenology-example-child-theme\

As demonstrated previously, the Child Theme will now appear in the Themes section of the WordPress Admin area, and can be activated like any other Theme.

Once you activate the Child Theme, you won't notice any differences whatsoever on the front end:

Page Using the Default Template

Why? Because you've not made any changes to any of the default content, templates, or styles. You will need to tell WordPress to use your Custom Page Template for a Page in order to see the changes.

So, either create a new Page, or else edit the Page for which you want to use the custom template. Look for the "Template" field in the "Page Attributes" metabox (click to enlarge):

Default Page Template applied to the Page

The drop-down box lists all of the possible Page templates that can be applied to the Page. Look for our new custom Template, "Page One Column Wide" (remember, this is the same name we used in the "Name" header tag in the "page-one-column-wide.php" template file):

Selecting our custom Page Template

Select the custom template file, and then save the Page. Now, when you view the Page, you should see the custom template applied to it:

Page Using Custom One Column Wide Template

And that's it! You've just created a Child Theme, and used it to define a custom Page Template! Here are the before and after screenshots, for comparison:

Page Using the Default TemplatePage Using Custom One Column Wide Template

I've also uploaded a ZIP file containing the example files "style.css" and "page-one-column-wide.php" used in this tutorial: oenology-example-child-theme.zip. Feel free to use however you'd like!

If you have any questions, please don't hesitate to ask. Though, I would prefer that you ask them in the Oenology Support Forum at wordpress.org, where official support for the Oenology Theme is provided, rather than in the comments.

Good luck, and happy Child Theming!

Custom WordPress Gravatars – The Right Way

Filed in Web DevelopmentTags: Gravatars, Themes, tutorials, WordPress

I recently (h/t: Nacin) came across this tutorial by Nenuno Creative that recommends bypassing WordPress core implementation of Gravatars in order to output custom Gravatars. Below, I present a brief tutorial for a much better way to implement custom Gravatars in a way that doesn't require bypassing WordPress' core functionality.

The Nenuno Creative tutorial presents the following "customizations" of Gravatars:

  1. Comment Author email address
  2. Custom default Gravatar image
  3. Custom Gravatar image size

The problem with their tutorial is that, assuming your Theme is using wp_list_comments() to output the comments list (and your Theme is using wp_list_comments() to output the comments list, isn't it?), you have no easy way to control where and how your custom-built Gravatar is displayed (at least, not without quite a bit of additional custom code) - as evinced by the author's recommendation:

I would recommend using this in the “comments.php” page, somewhere around “< ? php wp_list_comments(); ? >” or whatever similar you may have in your theme!

Not a terribly helpful implementation suggestion, is it? (And in truth, since wp_list_comments() outputs a Gravatar by default, it's actually a rather incorrect recommendation.) Fortunately, all of the above can be implemented in a much, much easier way.

First, wp_list_comments() by default outputs a 32x32px Gravatar based on the Comment Author email address. So, all we need to deal with are custom Gravatar size, and custom default Gravatar image.

Custom Gravatar size is as simple as passing the avatar_size argument to wp_list_comments(). The arguments passed to wp_list_comments() are an array, so to output an 80x80px Gravatar, replace the default call:

wp_list_comments();

With this:

wp_list_comments( 'avatar_size=80' );

Simple, right?

That just leaves us with defining a custom default Gravatar image. Admittedly, this part is a bit trickier, but still not terribly complicated. We will be using the built-in user-configuration setting for default Gravatar image. By default, the option list includes "Mystery Man", "blank" (no image), the Gravatar logo, an Identicon, a Wavatar, and a Monster ID:

Default Avatars

The default list of images available for use as the default avatar in WordPress, including Mystery Man, blank (no image), the Gravatar logo, Identicon, Wavatar, and Monster ID

We will be hooking into this list, using the avatar_defaults filter, in order to add a custom image to this list (h/t: WPEngineer).

Simply add the following to your Theme's functions.php file:

function mytheme_addgravatar( $avatar_defaults ) {
  $myavatar = get_bloginfo('template_directory') . '/images/avatar.gif';
  $avatar_defaults[$myavatar] = 'My Theme Custom Gravatar';

  return $avatar_defaults;
}
add_filter( 'avatar_defaults', 'mytheme_addgravatar' );

You will need to replace /images/avatar.gif with an appropriate image file, that you have uploaded to your Theme directory.

That's it! Now, just go to Settings -> Discussion, and you will see your custom image listed in the options for Default Avatar:

Default Avatar Setting List With Custom Image

The default avatar setting list with a custom image "My Theme Custom Gravatar" added to the list

Simply select your custom image, and save settings.

Voila! We've just implemented everything from the Nenuno Creative tutorial, in a way that uses, rather than bypasses, core WordPress functionality.