Thesis Box API

The Thesis Box API consists of three main parts:

  1. Core properties
  2. Core methods
  3. Options that connect to Thesis and WordPress in different ways

At a minimum, every Box must use some core properties and methods, so we’ll take a look at those first.

Although not all Boxes require options, the ones that do can achieve incredible things with a tiny amount of code. We’ll look at these last.

Before we can do any of that, though, we need to connect to the Thesis Box API, so let’s do that now.

Invoke the Thesis Box API

When you create a Thesis Box, you automatically invoke the Thesis Box API. Through a coding concept known as inheritance, each Box receives a ton of functionality you can harness to bring your Box to life.

class my_box_class_name extends thesis_box {
	/* Box properties and methods go here */
}

In the snippet of code above, notice extends thesis_box—this is how your Box inherits all the basic Box functionality and the API goodness.

And now that you’re connected to the API, you’re ready to experience the power of Thesis Boxes!

Core Box Properties

Every Box has a set of core properties and methods that determine what the Box is and how it behaves. We’ll start by looking at the properties you can use to create precisely the kind of Box you need, and then we’ll look at the methods that will bring your Box to life.

$type

The $type property determines the basic functionality of a Box. It is a public property and should be declared like so:

public $type = 'box';

There are three basic types of Thesis Boxes, and thus, three possible values for the $type property:

  1. box
  2. rotator
  3. false

Note: All Boxes are considered to be of type box by default. You only need to include a $type property if your Box is of type rotator or false.

The first two types, box and rotator, are intended for Boxes that output HTML for the Skin. Examples of these kinds of Boxes include:

  • Nav Menu: box
  • Site Title: box
  • Post Box: rotator
  • Query Box: rotator

Boxes are intended to output a specific piece of information, but rotators can output many different pieces of information (indeed, anything you put into them). Both of these types of Boxes appear for use in the Thesis Skin Editor.

The third type of Box, false, is reserved for Boxes that don’t output HTML in templates or else hook their output into place. These types of Boxes do not appear in the Thesis Skin Editor. Examples include:

  • Google Analytics — hooks output into place
  • 404 Page — filters the WP_Query and hooks output into place
  • Home Page SEO — creates options that are accessible to other Boxes via the Thesis General API

$title

All Boxes of type box and rotator require a $title. Titles are public properties used to identify Boxes within the Thesis interface, and they can be translated into other languages, too.

Because they are translatable, titles must be declared in a special Box method called translate(), and the title text must be wrapped in a translation function, __('text', 'namespace'):

protected function translate() {
	$this->title = __('My Box Title', 'my_box_namespace');
}

In the example above, the Box title is My Box Title, and the namespace is my_box_namespace.

$name

By default, all Boxes are single-instance, and therefore, they only need a $title to distinguish themselves within the Thesis interface.

Some Boxes, however, need to be multi-instance, and these Boxes require an additional way to distinguish each instance within the Thesis interface. Enter the public $name property which, like the $title, should be set up for translation:

protected function translate() {
	$this->title = __('My Box Title', 'my_box_namespace');
	$this->name = __('My Instance Name', 'my_box_namespace');
}

Note: In the example above, I’ve included both the $title and $name parameters because in practice, you will need to include both in the translate() method of your Box.

If you declare a $name property within your Box, Thesis will automatically detect this and allow multiple instances of your Box in Skins. Examples of multiple-instance Boxes in Thesis include:

  • Nav Menu: box
  • Text Box: box
  • Widgets: box
  • Post Box: rotator
  • Query Box: rotator

$head

By default, Boxes of type box and rotator are considered to be <body> Boxes—that is, they are intended to appear in the Thesis Skin Editor and output inside the HTML <body> tag.

Some Boxes, however, handle functionality that requires output inside the HTML <head> element. Thesis contains a separate interface for $head Boxes, accessible through the “HTML Head” link in the Thesis Site menu.

If your Box belongs in the document <head>, then you should include the public $head property, like so:

public $head = true;

If your Box does not belong in the document <head>, then you should not declare a $head property!

$dependents

Some rotator Boxes are associated with certain pieces of output, and the $dependents property determines these associations. This concept is best illustrated with an example, so let’s look at the Thesis Post Box, which has many dependents.

The Post Box exists to output the data associated with posts and pages in your WordPress database. Each post or page contains many different pieces of data that make it unique, so for the Post Box to be effective, it must be able to access all this data.

As we learned earlier, Boxes of type box are intended to output specific pieces of information. Based on this, it’s clear that each piece of post/page data should be represented by a Box.

The $dependents property defines a relationship between a rotator and its box dependents, and it also ties dependents to the parent rotator throughout the Thesis interface.

A valid $dependents property is an array of the PHP class names of dependent Boxes. Here’s what the Post Box $dependents property looks like:

public $dependents = array(
	'thesis_post_headline',
	'thesis_post_date',
	'thesis_post_author',
	'thesis_post_author_avatar',
	'thesis_post_author_description',
	'thesis_post_edit',
	'thesis_post_content',
	'thesis_post_excerpt',
	'thesis_post_num_comments',
	'thesis_post_categories',
	'thesis_post_tags',
	'thesis_post_image',
	'thesis_post_thumbnail',
	'thesis_wp_featured_image');

Thanks to that simple declaration, every Post Box that gets included in a Thesis Skin has access to 14 key pieces of post/page data—headline, date, author name, post content, and more!

$children

When rotator Boxes with $dependents appear in the Thesis Skin Editor, they are empty by default.

If you want your rotator Box to contain certain dependents by default, then you must also specify a public $children property, which is an array of dependent Box class names (similar to the $dependents property above).

Here’s how that works for the Post Box, which includes 4 children whenever a new Post Box instance is added to a Skin:

public $children = array(
	'thesis_post_headline',
	'thesis_post_author',
	'thesis_post_edit',
	'thesis_post_content');

Thanks to that little bit of code above, every time a new Post Box is added to a template in the Thesis Skin Editor, it will contain a post headline, post author, edit link, and the post content. The rest of the dependent Boxes will appear in an area known as the tray, where they can be added to the Post Box if desired.

$templates

By default, both normal and rotator Boxes are available on every type of template in the Thesis Skin Editor.

However, some Boxes exist to provide functionality for specific kinds of templates, and their presence on other templates does not make any sense. Two great examples of this are the previous and next post links, which only work when placed in the Single template (or one of its descendants).

To constrain the templates on which your Box is available, simply add a public $templates property indicating the appropriate templates in an array, like so:

/* Box only appears on the Single template and its descendants: */
public $templates = array('single');

/* Box only appears on the Single and Page templates and their descendants: */
public $templates = array(
	'single',
	'page');

There are 4 basic template types available here:

  1. home
  2. single
  3. page
  4. archive

By default, Boxes appear on all 4 template types, so your $templates array should never contain more than 3 templates.

Note: All Boxes are available on custom templates, regardless of what is specified in the $templates property.

$switch

In the Thesis Skin Editor, rotator Boxes appear with a toggle switch that can be clicked to reveal the interior contents of the rotator. By default, this toggle switch is off, and the rotator is closed.

If your rotator Box should always be open by default in the Thesis Skin Editor, then you simply need to include a public $switch property and set it to true, like this:

public $switch = true;

$filters

The $filters property can be used to modify Box admin page functionality.

Core Box Methods

All Boxes contain a suite of core methods that are responsible for standardized Box functionality within Thesis. Let’s take a closer look at these methods and how you can use them.

translate()

protected function translate() {
	/* $this->title and $this->name should be declared here */
	/* use translation functions for all text: __('your text', 'my_box_namespace') */
}

We first saw the translate() method while covering the Box $title and $name properties above.

By placing your vital Box text the translate() method and wrapping it in a translation function, __('your text', 'my_box_namespace'), you enable your Box to be translated into other languages.

Note: In the translation functions above, 'my_box_namespace' is the namespace for your text. We recommend making this namespace the same as your Box class name, as this convention will make it easier for the Thesis community to translate your work!

construct()

protected function construct() {
	/* Runs once per Box instance during initialization */
}

If your Box needs to run filters or hooks (or perform any other kind of initialization on a per-instance basis), then you will probably want to include those calls in the construct() method.

For those of you familiar with PHP classes, this method is really just a pseudo-constructor (mimicking __construct()) that enables each Box to perform its own, unique initialization sequence.

Important Performance Note: Keep in mind that the construct() method runs on every page load—on both the front and back ends—so it is a bad idea to do a lot of processing here.

If you need to initialize functionality on a per-template basis (specifically, only on those templates where your Box appears), then you should use the preload() method.

preload()

public function preload() {
	/* Only runs on templates in which this Box appears. */
}

In contrast to the construct() method, which runs on every page load, the preload() method only runs on the front end, and only on templates on which your Box appears.

Because of this, the preload() method is the perfect way to initialize certain Box functionality precisely when you need it. Specifically, this is the perfect place to initialize scripts or to run conditional hooks or filters that should only run on specific templates.

html()

public function html($args = array()) {
	extract($args = is_array($args) ? $args : array());
	/* Box HTML output should be echoed here */
}

The html() method is the primary output method for Boxes that appear in Thesis templates. Rotators and normal Boxes require this method for proper functionality, but Boxes of $type = false do not.

When constructing your html() method, follow these guidelines for consistent, standardized results:

  • Always include the $args = array() parameter, as shown in the example code above.
  • Extract the $args parameter using the command shown. At the very least, this will provide you with a $depth property that you can use to ensure your output is indented properly (in the HTML source).
  • Place your Box output within either an echo or printf() function (instead of simply returning it).
For examples of html() methods, have a look at the following file within Thesis:

/thesis/lib/core/skin/boxes.php

Box Options

Core Box properties and methods are important for establishing basic functionality. However, for dynamic, unique functionality, you need more than just core properties and methods—you need options.

Thanks to 6 different types of options, Boxes can connect to both Thesis and WordPress in simple, powerful ways:

  • Class-based: Options that apply to every instance of a Box
  • Instance-based: Options that are unique to each instance of a Box
  • HTML: Instance-based options that provide for variable HTML output
  • Post meta: Add options to the WordPress post editing screen
  • Term: Add options WordPress term editing screens (category, tag, taxonomy)
  • Template: Add options to templates in the Thesis Skin Editor

Each option type consists of a reserved method and a reserved property that you can use to achieve your desired outcome. Also, because each method uses the Thesis options API array format, it’s easy to create the exact options you need.

Class and Instance-based Options

/* class-based options */
protected function class_options() { }

/* instance-based options */
protected function options() { }

For an exhaustive look at how class and instance-based options work, please refer to the documentation on Box Options and Admin Pages.

HTML Options

protected function html_options() { }

Unlike class and instance-based options, HTML options do not have admin pages. Instead, Box HTML options are accessible from either the Skin Editor or the HTML Head Editor (for Boxes where $head = true), where they can be controlled by both Skin developers and users.

Typically, HTML options are limited to the following, predictable items:

  • HTML tag (<div>, <span>, <p>, etc.)
  • HTML id
  • HTML class

Because of this predictability, Thesis contains an API method that you can use as a shortcut when creating HTML options for your Box. Here’s how that works:

/* Using the Thesis API to create class and id HTML options */
protected function html_options {
	global $thesis;
	return $thesis->api->html_options();
}

The above example would result in a Box with HTML options for an id and class, but not an HTML tag.

To add a tag, simply include two parameters in your call to $thesis->api->html_options(): an array containing the possible HTML tags, and a default value for the tag. Here’s what that looks like:

/* Also create an HTML tag option */
protected function html_options {
	global $thesis;
	return $thesis->api->html_options(array(
		'div' => 'div',
		'p' => 'p',
		'span' => 'span'), 'div');
}

In addition to id and class options, the above snippet provides an HTML tag option with a choice between div, p, or span (with div as the default).

Like class and instance-based options, HTML option values are accessible from the Box $options property:

/* To reference HTML options in your Box code... */
$this->options['option_id']

Important! Values for class-based, instance-based, and HTML options are all contained in a single Box property, $options. In order to avoid data conflicts, ensure that your option_id values are unique for these 3 types of options.

If you use the Thesis API shortcut to generate your HTML options, you’ll end up with the following option_id values for your HTML options:

  • HTML tag: html
  • HTML id: id
  • HTML class: class

Remember! The option_id values for Box HTML options should be unique, or else they will conflict with option_id values from class or instance-based options.

An easy way to deal with the potential conflict mentioned above is to only use id, class, and html for HTML options.

WordPress Post Meta

/* reserved method */
protected function post_meta() { }

/* reserved property (with sample option reference) */
$this->post_meta['option_id']

If you’ve ever added post meta options to WordPress, then you know what a pain in the ass this process can be. Worse, adding your options is only half the battle—you still have to write code to save the options, and then you also have to retrieve those options when you want to use them.

Thankfully, Thesis brings some sanity to the process of creating WordPress post meta options. Instead of treating post meta as something special and idiosyncratic, Thesis treats post meta just like it treats all other options.

Using the post_meta() reserved method, you can simply feed Thesis an array in options API syntax module array format, and Thesis will output, save, and retrieve your post meta options for you.

You don’t have to know any WordPress hooks; you don’t have to worry about whether or not you’re saving options in a secure way; and you don’t have to retrieve the post meta data by making any crazy function calls in your code.

Instead, you simply tell Thesis that you want to add post_meta() to your Box, and Thesis handles the rest.

Syntax note: Post meta options use the options module syntax, so keep that in mind when constructing your post meta options array.

In addition to the normal options module syntax parameters, post meta options allow for 3 additional parameters:

  • context — normal, advanced, or side
  • priority — high, core, default or low
  • exclude — array of post types this post meta should be excluded from

For more information on the context and priority parameters, please see the add_meta_box() documentation.

WordPress Term Options (Category, Tag, and Taxonomy)

/* reserved method */
protected function term_options() { }

/* reserved property (with sample option reference) */
$this->term_options['option_id']

Posts and pages aren’t the only types of pages you might want to customize within WordPress. Category, tag, and taxonomy pages are critically important to many sites, but WordPress doesn’t afford the same level of customization and flexibility on these types of pages.

Despite this, and thanks to Thesis Box term options, you can now add options to these pages just like you can add post meta to normal posts and pages.

Simply supply a term_options() method, and Thesis will do the rest of the heavy lifting for you. Not only will Thesis output options on edit term pages in the WordPress interface, but it will also retrieve those options for you precisely when you need them.

Attention! Option grouping, dependence, and options objects are not supported in term options. For best results, just supply simple, straightforward options here.

WordPress Custom Post Types and Taxonomies

/* reserved method */
protected function post_types() { }

/* reserved method */
protected function post_type_taxonomies() { }

Boxes can also register custom post types (CPT) and taxonomies for extended CMS functionality. Use the valet methods shown here as a shortcut to register your CPTs and taxonomies and to keep your codebase clean.

post_types()

When registering a CPT in WordPress, you must supply two pieces of information:

  • a reference key for your CPT, and…
  • an arguments array to describe how your CPT should work

The Thesis Box API accepts these two pieces of information in the following manner:

protected function post_types() {
	return array(
		'my_cpt_reference_key' => array(
			'description' => __('Sample Custom Post Type', 'my_namespace'),
			'exclude_from_search' => true,
			'label' => __('My Sample CPT', 'my_namespace'),
			'labels' => array(
				'name' => __('Sample CPT', 'my_namespace'),
				'singluar_name' => __('Sample CPT', 'my_namespace'),
				'add_new' => __('Add New Sample CPT', 'my_namespace'),
				'add_new_item' => __('Add New Sample CPT', 'my_namespace'),
				'edit_item' => __('Edit Sample CPT', 'my_namespace'),
				'new_item' => __('New Sample CPT', 'my_namespace'),
				'all_items' => __('All Sample CPT', 'my_namespace'),
				'view_item' => __('View Sample CPT', 'my_namespace'),
				'search_items' => __('Search Sample CPT', 'my_namespace'),
				'not_found' => __('No Sample CPT found', 'my_namespace'),
				'not_found_in_trash' => __('No Sample CPT found in trash', 'my_namespace'),
				'menu_name' => __('Sample CPT', 'my_namespace')),
			'menu_icon' => 'dashicons-welcome-add-page',
			'menu_position' => 40,
			'public' => true,
			'publicly_queryable' => false,
			'query_var' => false,
			'rewrite' => false,
			'show_in_nav_menus' => false));
}

Pro tip: Register multiple post types at once by adding additional reference_key => [arguments array] pairs.

post_type_taxonomies()

The Thesis Box API also makes it easy to register a custom taxonomy to go with your CPT.

To associate a taxonomy with your CPT, simply use the my_cpt_reference_key value from your CPT when you register your taxonomy (highlighted below):

protected function post_type_taxonomies() {
	return array(
		'my_taxonomy_reference_key' => array(
			'cpt' => 'my_cpt_reference_key',
			'taxonomy' => array(
				'labels' => array(
					'name' => __('Custom Taxonomy', 'my_namespace'),
					'singular_name' => __('Custom Taxonomy', 'my_namespace'),
					'menu_name' => __('Custom Taxonomy', 'my_namespace'),
					'all_items' = __('All Custom Taxonomies', 'my_namespace'),
					'edit_item' => __('Edit Custom Taxonomy', 'my_namespace'),
					'view_item' => __('View Custom Taxonomy', 'my_namespace'),
					'update_item' => __('Update Custom Taxonomy', 'my_namespace'),
					'add_new_item' => __('Add New Custom Taxonomy', 'my_namespace'),
					'new_item_name' => __('New Custom Taxonomy', 'my_namespace'),
					'search_items' => __('Search Custom Taxonomies', 'my_namespace'),
					'popular_items' => __('Popular Custom Taxonomies', 'my_namespace'),
					'separate_items_with_commas' => __('Separate Custom Taxonomies with commas', 'my_namespace'),
					'add_or_remove_items' => __('Add or remove Custom Taxonomies', 'my_namespace'),
					'choose_from_most_used' => __('Choose from the most used Custom Taxonomies', 'my_namespace'),
					'not_found' => __('No Custom Taxonomies found', 'my_namespace'),
					'back_to_items' => '← '. __('Back to Custom Taxonomies', 'my_namespace'),
				'rewrite' => false)));
}

As is the case with post_types(), you can register multiple taxonomies at once simply by including additional reference key => [arguments array] pairs.

Thesis Template Options

/* reserved method */
protected function template_options() { }

/* reserved property (with sample option reference) */
$this->template_options['option_id']

Certain kinds of data only make sense relative to a particular template, and this is why template options exist.

For example, the Thesis WP Loop Box has an option to control the number of posts per page on different templates. Using this option, a user could choose to show 10 posts on the home template, but she could also choose to show 25 posts on archive templates.

If your Box requires options that only make sense when saved relative to a template, you should add these as template_options().

Syntax note: Template options use the options module syntax, so keep that in mind when constructing your template options array.

In addition to the regular options module parameters, template options allow for an exclude parameter that you can use to prevent options from appearing on certain templates.

Simply return an array of the templates you’d like to exclude (possible values: home, single, page, and archive), and boom—precise control over your template options.

Path and Directory Constants for Add-on Boxes

Add-on Boxes for Thesis differ from core Boxes in one key way: They are located in their own folders inside the Thesis custom filesystem.

There are countless situations where add-on Boxes may need to to invoke their own files or code libraries, and Thesis automatically creates two constants developers can use to reference included files:

  1. {BOX_CLASS_NAME} — remote path reference for including files on the back end
  2. {BOX_CLASS_NAME}_URL — directory reference for including files on the front end

For example, the Social Media Profiles Box needs to include a CSS file called icons.css to serve social media icons. Because this CSS file is output on the front end, we’ll use the directory reference to point to the file:

THESIS_SOCIAL_PROFILES_URL. '/icons.css'

In the code above, note that THESIS_SOCIAL_PROFILES is the uppercase version of the Social Media Profiles Box class name, thesis_social_profiles.

In practice, the Social Media Profiles Box uses the thesis_font_stylesheet array filter to serve its CSS immediately before the Skin CSS file. Here’s what that looks like:

/* This goes inside the Box construct() or preload() methods: */
add_filter('thesis_font_stylesheet', array($this, 'css'));

/* Elsewhere inside the thesis_social_profiles class: */
public function css($css) {
	$css[$this->_class] = THESIS_SOCIAL_PROFILES_URL. '/icons.css';
	return $css;
}