A small primer on theme mods

Oh, the many things I encounter while doing reviews is amazing.

One of the reasons I love contributing to the review team is to get a better understanding of how WordPress at its core works and it is because of this I feel like there are some things that still are not being mentioned or shared.

A fairly good example of this is what I saw today. I’ve seen this on several themes but I think I finally reached a point where it really, truly irks me.

What are settings?

WordPress themes can use two things to save user inputs – or better yet theme mods. The neat part is there are two ways those can be saved. Using option or theme_mod when registering a setting in the customizer. What I want to focus on for this is the use of theme_modsince it is the recommended method for most themes. Notice I say most. There are cases where it makes sense to use option but that’s for another time. The WordPress theme mods are saved and retrieved using a few functions.

  • get_theme_mods() – gets all theme settings
  • get_theme_mod() – gets a single setting
  • set_theme_mod() saves a theme setting

Now, there are two other functions for theme mods.

  • remove_theme_mod() – remove a single theme setting
  • remove_theme_mods() – removes all theme settings

Those are least likely to be used but they are good to know.

How it works

The WordPress customizer is magic. Okay, not completely and I only say that because if you look at how things work in the JavaScript file it quite literally says, “return magic;

The way the customizer saves things is by using a few object methods. It uses the save() method, which calls the update() method, and tfinally the set_root_value() method of the Setting class. It’s here where our setting actually gets saved.

If we look over the highlighted code we can see what is actually happening.

protected function set_root_value( $value ) {
	$id_base = $this->id_data['base'];
	if ( 'option' === $this->type ) {
		$autoload = true;
		if ( isset( self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'] ) ) {
			$autoload = self::$aggregated_multidimensionals[ $this->type ][ $this->id_data['base'] ]['autoload'];
		}
		return update_option( $id_base, $value, $autoload );
	} elseif ( 'theme_mod' === $this->type ) {
		set_theme_mod( $id_base, $value );
		return true;
	} else {
		/*
		 * Any WP_Customize_Setting subclass implementing aggregate multidimensional
		 * will need to override this method to obtain the data from the appropriate
		 * location.
		 */
		return false;
	}
}

The default setting for registering a theme option is theme_mod and what this means is that when the user clicks that save button, the function set_theme_mod() will be triggered and the setting will be saved to the database. Super cool! Now, what does that little function actually do?

Well, let’s take a look over it:

function set_theme_mod( $name, $value ) {
	$mods = get_theme_mods();
	$old_value = isset( $mods[ $name ] ) ? $mods[ $name ] : false;

	/**
	 * Filters the theme mod value on save.
	 *
	 * The dynamic portion of the hook name, `$name`, refers to the key name of
	 * the modification array. For example, 'header_textcolor', 'header_image',
	 * and so on depending on the theme options.
	 *
	 * @since 3.9.0
	 *
	 * @param string $value     The new value of the theme mod.
	 * @param string $old_value The current value of the theme mod.
	 */
	$mods[ $name ] = apply_filters( "pre_set_theme_mod_{$name}", $value, $old_value );

	$theme = get_option( 'stylesheet' );
	update_option( "theme_mods_$theme", $mods );
}

It gets all the theme mods, then creates a filter for us to use, gets the name of the currently active theme, and finally updates an option.

An option?

Yes. An option. I know. I know. We were talking about theme mods but the way the customizer works with theme_mods is by creating an associative array per theme. For example, if my theme were called For Real Yo, the $theme would be for-real-yo.

WordPress then turns it to a slug. So, the best way to get those options would be to get the option or use the core functions get_theme_mod() and get_theme_mods() to do things for me and because we like using good practices we use get_theme_mod() in order to get the single setting – or rather theme_mod.

You are probably wondering what get_theme_mods() does. I know I did when I first read the code.

function get_theme_mods() {
	$theme_slug = get_option( 'stylesheet' );
	$mods = get_option( "theme_mods_$theme_slug" );
	if ( false === $mods ) {
		$theme_name = get_option( 'current_theme' );
		if ( false === $theme_name )
			$theme_name = wp_get_theme()->get('Name');
		$mods = get_option( "mods_$theme_name" ); // Deprecated location.
		if ( is_admin() && false !== $mods ) {
			update_option( "theme_mods_$theme_slug", $mods );
			delete_option( "mods_$theme_name" );
		}
	}
	return $mods;
}

From the core code, we can see that it gets the theme slug, gets the option ( from the options table ) for the active theme, then it checks to see if it is populated or not, and finally returns the array of theme_mods.

So, why this post?

I am making this because the code that I stumbled across looked a little like:

<?php
/**
 *  Default theme options
 */
if ( ! function_exists( 'for_real_yo_default_options' ) ) :
	function for_real_yo_default_options() {
		$default_options = array(
			/* super long list of "defaults" */
		);
		return apply_filters( 'for_real_yo_defaults', $default_options );
	}
endif;


/**
*  Get theme options
*/
if ( ! function_exists( 'for_real_yo_theme_options' ) ) :

	function for_real_yo_theme_options() {

		$for_real_yo_defaults = for_real_yo_default_options();

		$for_real_yo_option_values = get_theme_mod( 'for_real_yo' );

		if ( is_array( $for_real_yo_option_values ) ) {
			return array_merge( $for_real_yo_defaults ,$for_real_yo_option_values );
		} else {
			return $for_real_yo_defaults;
		}
	}
endif;

Looks rather harmless, right? It is until you realize how they were registering the setting.

$wp_customize->add_setting(
	'for_real_yo[rando-setting]',
	array(
		'default' 			=> 'title-text',
		'sanitize_callback' => 'for_real_yo_sanitize_select'
	)
);

If you can spot the issue, awesome. If not, it is creating an array for one setting of a setting. Yes, a little odd to say the least but I’ll show a quick example.

Let’s say we are comparing one of the core themes with our above code. Okay, let us look at the returned array from each one. Twenty Seventeen would yeild something like:

Array
(
    [header_image] => path/to/file
    [header_image_data] => stdClass Object
        (
            [attachment_id] => id
            [url] => path/to/file
            [thumbnail_url] => path/to/file
            [height] => 1198
            [width] => 2000
        )

    [page_layout] => one-column
    [header_textcolor] => cfe23d
    [colorscheme] => light
    [colorscheme_hue] => 0
)

Now, if we look at the above example’s way of registering you can see the difference much better.

Array
(
    [for_real_yo] => Array
        (
            [some_setting] => 
            [another_setting] => 
            [top_bar_left] => menu
            [right_social] => 
            [right_hours] => 
        )

)

Hopefully this does help in understanding how theme_mods are saved and retrieved and does at least help out one person.

A metabox for your layout options

It’s no surprise I can be vocal when I am reviewing a theme. Many know that I’ll spurt out what I end up seeing in a lot of themes. There is one thing that really does drive me crazy though and that is when people copy and paste code to their theme without actually knowing how the code actually works.

One file that has really been rather popular is using a metabox in order to choose the layout of the post or page. That’s great. I love that ability but then again who doesn’t love having that control? I think what drives me bonkers is that this code is super predictable before the file is opened. The file adds two actions. One to add_meta_boxes and the second to the save_post hooks. Great! Very super simplistic and hard to mess up, right?

I created a gist with the name of the theme changed. The code is the same that I’ve seen in many other themes though. From authors who have several themes in the repo to new authors to the repo.

One of the first things that you may notice is the use of two globals.

global $post, $deargodwhy_sidebar_layout;

First there should be no reason for that and second those hooks pass the $post object. We’ll look at the first one: add_meta_boxes

Using the developer resources as a guide we see that the hook for adding metaboxes uses two arguments. The post type and the post.

do_action( 'add_meta_boxes', string $post_type, WP_Post $post )

The first one being the string of the current post type and the second being the WordPress post object. Now, what’s super cool about that is that we can now register a metabox in any post type we want and it does on every post type if we don’t pay attention to what we are doing. There is also one more hook we could potentially use in order to use a metabox in only one specified post type. That hook is add_meta_boxes_{$post_type} and the developer docs does explain it a little better. For example, if you wanted to add a metabox to only your EDD downloads, you could do something like:

add_action( 'add_meta_boxes_download', 'jmc_download_extra_metaboxes', 10 );
function jmc_download_extra_metaboxes( $post ) {
	// Do our magic here.
}

In order to now add our metabox we do need to use the function add_meta_box() so let’s take a look at how that function is used.

add_meta_box( $id, $title, $callback, $screen = null, $context = 'advanced', $priority = 'default', $callback_args = null )

Now, if you want to take a closer look at what each one of those parameters actually does then I suggest you take a look over the developer docs. It is well worth your time if you really want to understand how to create a better user experience and understand how WordPress creates those.

Another thing I wanted to look over was the save_post callback being used. The biggest issue is the use of the foreach() loop.

foreach( $deargodwhy_sidebar_layout as $field ){  
        //Execute this saving function
        $old = get_post_meta( $post_id, 'deargodwhy_sidebar_layout', true ); 
        $new = sanitize_text_field( $_POST['deargodwhy_sidebar_layout'] );
        if ( $new && $new != $old ) {  
            update_post_meta($post_id, 'deargodwhy_sidebar_layout', $new );  
        } elseif ('' == $new && $old ) {  
            delete_post_meta( $post_id,'deargodwhy_sidebar_layout',  $old );  
        } 
     }

The reason is it is creating an unnecessary loop. The only thing that needs to be checked is the value being input and to make sure that it is a valid option. A quick change to the code and we have:

if ( ! empty( $_POST['deargodwhy_sidebar_layout'] )
	&& in_array( $_POST['deargodwhy_sidebar_layout'], array( 'right-sidebar', 'no-sidebar' ), true )
	) {
	update_post_meta( $post_id, 'deargodwhy_sidebar_layout', $_POST['deargodwhy_sidebar_layout'] );
}

Knowing those things we could make changes to the file and not only will we have a better understanding of how WordPress creates metaboxes but we have a file that doesn’t pollute the $GLOBALS with info that we only use in one place. If you look at what those changes were in the diff, you will see that not a lot was changed. It only looks that way since I removed a lot of the linting errors.

My tour of creating a PHPCodeSniffer Standard

It’s no surprise I like to learn new things. I also like to read things when I can. Okay, a lot of the time I skim through things but I make an effort to learn from it.

The last couple of weeks I’ve looked at working with the PHPCodeSniffer. I installed it and never really played with it. Not until last week did I realize my version was out of date. Easy fix but something to keep in mind. The current version at the time of this writing is 2.7.1 and that’s what I am currently running on my Windows machine as well as my MBP.

So, here are some of the things I learned from attempting to create a standard and a sniff.

Lessons Learned

  • Read the docs
  • Carefully read the docs
  • Experiment

One of the first things to understand is that you need to know where your PHPCS standards reside.  There you will see a series of folders and files. The one that we will focus on is the Standards folder. This is where our newly created Standards will live.

The steps

We will outline the steps needed to create both a standard as well as a sniff. They are:

  1. Create the directories
  2. Create the XML file
  3. Create the sniff or sniffs if you want more

Sounds super simple right?

So let’s move on!

The first thing we will do is create the directories. The first one is the name of our standard. The second directory will be Sniffs and this is where all of our sniffs will reside. For example, WordPress standards looks like the following image:

Inside of the folder we will then create the ruleset.xml file with the needed information for our standard. It will look something like the following image:

Now, we can finally create our sniffs. But wait there is one thing you should know before making this and that is that you need to have a category folder.

Why?

It makes it easier to organize and know what we are looking for as well. For the sake of this post, I created an Example folder and inside of that I created a ListSniff.php file. Pay close attention to that detail as it will matter down the line. I learned this one because of errors I kept getting.

So, our new folder structure should look a little like:

codesniffer\standards\
codesniffer\standards\YourStandard
codesniffer\standards\YourStandard\ruleset.xml
codesniffer\standards\YourStandard\Sniffs
codesniffer\standards\YourStandard\Sniffs\Example
codesniffer\standards\YourStandard\Sniffs\Example\ListSniff.php

Now we can create our sniff!

This is where the fun really begins for some.

The important thing here is both the file and the class inside of the file must end with Sniff. For my example I named it ListSniff.php so the class would look like:

<?php
/** Example class created for demonstration purposes only **/
class YourStandard_Sniffs_Example_ListSniff implements PHP_CodeSniffer_Sniff {

	public function register() {
		return array();
	} // end register()

	public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) {

		// Tokenize the file, right?
		$tokens = $phpcsFile->getTokens();

		// We need this in order show what the error actually is.
		$phpcsFile->addError( $error, $stackPtr, $code = '', $data = array(), $severity = 0, $fixable = false );

		// We can even add a warning if we want.
		$phpcsFile->addWarning( $warning, $stackPtr, $code = '', $data = array(), $severity = 0, $fixable = false );
	} //end process()
}

You will see two very interesting things here. The first one being the naming of the class. It needs to be:

class {Folder of the standard name}_{the Sniffs folder}_{subfolder of Sniffs}_{your sniff}Sniff

And the second being the implements PHP_CodeSniffer_Sniff. This is straight from their documentation:

Each sniff must implement the PHP_CodeSniffer_Sniff interface so that PHP_CodeSniffer knows that it should instantiate the sniff once it’s invoked.

The reason is because the PHP_CodeSniffer_Sniff interface has two methods that need to be utilized. The register() and process() methods.

The methods

The first one – register – simply does that. You register what tokens you want the CodeSniffer to catch. PHP.net does provide a super handy list with all the available tokens.

Now, let us take a look at how the addError and addWarning sort of work so you can get an idea of what you can do.

First the addError:

/**
@param string  $error    The error message.
@param int     $line     The line on which the error occurred.
@param int     $column   The column at which the error occurred.
@param string  $code     A violation code unique to the sniff message.
@param array   $data     Replacements for the error message.
@param int     $severity The severity level for this error. A value of 0
                         will be converted into the default severity level.
@param boolean $fixable  Can the error be fixed by the sniff?
*/

What’s really nice is that the addWarning does nearly the same:

/**
@param string  $warning  The error message.
@param int     $line     The line on which the warning occurred.
@param int     $column   The column at which the warning occurred.
@param string  $code     A violation code unique to the sniff message.
@param array   $data     Replacements for the warning message.
@param int     $severity The severity level for this warning. A value of 0
                         will be converted into the default severity level.
@param boolean $fixable  Can the warning be fixed by the sniff?
*/

With that I created a random test sniff. It turned out a little like:

class Examplee_Sniffs_Example_FunctionSniff implements PHP_CodeSniffer_Sniff {

	public function register() {
		return array( T_FUNCTION );
	} // end register()

	public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) {

		// Tokenize it!
		$tokens = $phpcsFile->getTokens();

		// We want to check.
		if ( $tokens[ $stackPtr ]['content'] ) {

			// build up our message to show on the report.
			$warn = 'Make sure %s is prefixed';

			// build up the array of data we want to pass
			$data = array( trim( $phpcsFile->getDeclarationName( $stackPtr ) ) );

			// finally we add our warning. Could use addError().
			$phpcsFile->addWarning( $warn, $stackPtr, 'found', $data );
		}
	} //end process()
}

I did try it out on Twenty Seventeen functions file and got the following:

FOUND 0 ERRORS AND 14 WARNINGS AFFECTING 14 LINES
----------------------------------------------------------------------
  27 | WARNING | Make sure twentyseventeen_setup is prefixed
 200 | WARNING | Make sure twentyseventeen_content_width is prefixed
 222 | WARNING | Make sure twentyseventeen_fonts_url is prefixed
 257 | WARNING | Make sure twentyseventeen_resource_hints is prefixed
 274 | WARNING | Make sure twentyseventeen_widgets_init is prefixed
 315 | WARNING | Make sure twentyseventeen_excerpt_more is prefixed
 336 | WARNING | Make sure twentyseventeen_javascript_detection is
     |         | prefixed
 344 | WARNING | Make sure twentyseventeen_pingback_header is
     |         | prefixed
 354 | WARNING | Make sure twentyseventeen_colors_css_wrap is
     |         | prefixed
 371 | WARNING | Make sure twentyseventeen_scripts is prefixed
 433 | WARNING | Make sure twentyseventeen_content_image_sizes_attr
     |         | is prefixed
 460 | WARNING | Make sure twentyseventeen_header_image_tag is
     |         | prefixed
 479 | WARNING | Make sure twentyseventeen_post_thumbnail_sizes_attr
     |         | is prefixed
 499 | WARNING | Make sure twentyseventeen_front_page_template is
     |         | prefixed
----------------------------------------------------------------------

So you can see some versatility when using the PHPCodeSniffer. If you really want to help out the Theme Review team then I highly recommend heading over to the github repo and helping out.

As for me, I’ll be digging more into how to create random tests because I like dabbling and breaking those things.

Creating a diff file

The other day I made a quick video on how to create PHPCS reports. Later on during the day I was asked about creating a patch to meta. Of course I’m going to make another video to help somebody else out.

In the video I go over on how to create a diff file using SVN and atom. With that file you can submit patches to core and meta.

There are two places to look for. If you are submitting a new ticket, you will see a checkbox that will take you to an upload screen.

Or if you are contributing to an already existing ticket you will see a field where you can upload files.

Hope this helps some of you out!

Creating sample PHPCS reports

I created a quick video in hopes to help some people understand the great thing that is using the PHP_CodeSniffer and how good it can be for not only developing plugins but WordPress themes as well.

In the video I create two sample reports. The first one a source report and the second just a summary report. The documentation does provide some useful information to help along the way in creating those reports.

Hope this helps some people out!

Theme Review tips, tricks, and take aways

WordPress theme reviews are:

  • Fun
  • Entertaining
  • Demanding
  • Awesome
  • Time consuming

There are more but those are the ones that came to mind first. The last one is the one I really want to focus on the most and there is a reason for it. Recently, the review team posted a call to tips on theme reviews. I chimed in and now I feel a little more compelled to expand a little more on my personal site.

I’ve been doing reviews for quite some time and have got quite a few reviews under my belt. Currently about 2,600 that have my name attached to them. Yeah. Safe to say I’ve looked over a lot of code over the years. I have loved every single moment because I love knowing that I have helped out not only one person but an entire community by doing what I do. I am looking forward to being able to make more videos down the road to help others.

So, onward!

Tips

The biggest tip really is get your testing environment setup. My review setup is a little odd. I use Windows 7 as well as OSX 10.9.5 with VVV, Variable VVV, and the development subversion repository to test all themes. Yes, I like to live dangerously. The plugins I use are:

Active plugins

Extra plugins

As you can see I use quite a few plugins and each serve their own purpose. The extra plugins are not always active when I conduct my reviews. I only activate them when I want to try to break the theme or see if it does break.

A great tip is to always look at how core does things. Knowing how core works helps you out in knowing when a theme is creating too much content or even when it comes to explaining to an author how to better improve their theme.

Tricks

Now, the browser is Chrome and my editor of choice is Brackets. I got used to working with it and haven’t tried much else. Was never a fan of IDEs because I grew up looking at the markup in Notepad. Yes. Notepad. We all started out somewhere. I do like using the “Find in Files” feature and regular expressions to looks for certain things within the theme. I setup a few rules so it doesn’t search certain files or folders though the folder restriction is when I’m looking for core code and inline documentation.

regex-search

That’s great and all but that doesn’t really show much else. When I post a comment on the ticket and let the author know I often use one of two methods of letting them know what is still in need of fixing. The first template outlines the requirements and I bullet out what in particular needs to be addressed.

= Required =
Note all required items that theme needs to fix before theme can be approved

== a11y ==

== Code ==

== Core/Features ==

== Plugin Territory ==

== Documentation ==

== Language ==

== Options/Settings ==

== Styles/Scripts ==

= Recommend =

The second:

= Required =

=== header.php ===
* missing translation [L4,l6,L10]

=== functions.php
* plugin: `add_filter( 'show_admin_bar', '__return_false' );` please remove

= Recommend =
* The red on the navigation makes it a little hard to read some of the menu items, consider a darker shade or use a lighter text color

I have always liked using the second method because it forces me to go file by file. That is the reason it can take a long time to review a theme. Even more when some include frameworks. That’s files and folders to look over.

Take-aways

The biggest gain, of course, is that I’ve learned a lot about how WordPress works and how themes are created by many.

WordPress underscore template

The last few posts I’ve mentioned diving into creating an underscore theme. There is now one core ticket I’ve been keeping an eye on and will continue to do so until it is resolved.

Since the last post I did install the REST API plugin so this now means I am one step closer to converting this site to a project site. Yes. Expect things to break here this year. 🙂

A few links

In my quest for theming in JS I came a across few links that helped shed some light as to how WordPress does things not only within the customizer but in the admin areas. I love reading the inline docs for that reason. There are a few other tutorials and posts I came across that may also help others out there:

Great and wonderful resources. So let us write a little code!

JS code

One of the first things we want to do is enqueue our main JavaScript file and add jQuery and underscore as a dependency.

add_action( 'wp_enqueue_scripts', function(){
	wp_enqueue_style( 'default', get_stylesheet_uri() );
	
	$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
	
	wp_enqueue_script( 'jmc-main-js', get_template_directory_uri() . '/js/main.js', array( 'jquery', 'underscore' ) );
	wp_localize_script( 'jmc-main-js', 'site', array(
		'restURL' => get_rest_url(),
		'name' => get_bloginfo( 'name', 'display' ),
	) );
});

Awesome! In the above we have enqueued our stylesheet and our main JavaScript file we will use. In our file we will use something like:

_.templateSettings = {
	evaluate:    /<#([\s\S]+?)#>/g,
	interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
	escape:      /\{\{([^\}]+?)\}\}(?!\})/g,
};

// Site name
jQuery( document ).ready( function($){
	var titletemplate = _.template( $( '#site-title' ).html() );
	$( '#masthead ' ).append( titletemplate({name: site.name }) );
});

In the JS you see we create a new variable ( titletemplate ) and it stores the markup from the site-title jQuery is getting. From there we can now use the append() method to add the newly created markup to our #masthead element. What does it look like?

<script id="site-title" type="text/template">
	<h1 class="site-name">{{{ name }}}</h1>
</script>

Fairly neat, yeah? We have now attached the site’s name via JavaScript. Yeah, not a huge deal since you can also do it with basic PHP and WordPress core functions but it is something neat to experiment with specially if you want to use some neat JavaScript/CSS effects.

That’s great but what about posts? Because we declared our templateSettings in the global space we can use the core methods of handling underscore templates. So rather than using:

  • <%= %>
  • <%- %>
  • <% %>

Why the change?

There may be a few that ask why using mustache style and not ERB that underscore uses. The reason is because in some cases PHP will be setup to use ASP style tags and we don’t want any issues to arise from that. So, rather than having to list off another dependency and another file be loaded we instead use that small snippet that makes it work. That code can be found in the wp-util file and if we look at the code we can see what it is doing:

wp.template = _.memoize(function ( id ) {
	var compiled,
		/*
		 * Underscore's default ERB-style templates are incompatible with PHP
		 * when asp_tags is enabled, so WordPress uses Mustache-inspired templating syntax.
		 *
		 * @see trac ticket #22344.
		 */
		options = {
			evaluate:    /<#([\s\S]+?)#>/g,
			interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
			escape:      /\{\{([^\}]+?)\}\}(?!\})/g,
			variable:    'data'
		};

	return function ( data ) {
		compiled = compiled || _.template( $( '#tmpl-' + id ).html(), null, options );
		return compiled( data );
	};
});

It is simply passing an object with a few options. And with that we can now use:

  • {{ name }} for escaped data
  • {{{ name }}} for un-escaped data
  • <# _.each() #> to evaluate the code

So now if we had to iterate over an array of posts we can use underscore’s each() method to do so. It could look something like:

<script id="post-tpl" type="text/template">
<# _.each( posts, function( post ){ #>
	<article class="post" id="{{ post.id }}">
		<h2 class="post-title">{{{ post.title.rendered }}}</h2>
	</article>
<# }) #>
</script>

Great!

I will end it by noting that I am not using the tmpl- prefix because I am using underscore’s template() method and passing it our template directly. One advantage, I guess. So, go. Explore, break things, and learn from it!

Three sliders, one option, and a few tears later

Yes, sliders have a special place in my heart. Granted a super tiny place in my theme reviewer’s heart. Now, I’ve created a few tutorials, guides, resources, links, what you will on this site in order to share some of my insights into WordPress theme development and perhaps some WordPress theme reviews along the way.

There are a lot of things I have learned and a lot of things I had to learn. I think the biggest takeaway from this post will be that integrating a slider plugin to a theme is fairly easy to do but a pain in the butt to fully integrate.

So, let’s get the show on the road!

First steps

Okay, we need to figure out first what slider we would like to play nice with, right? I chose sort of at random three different plugins that all create sliders.

I was going to use Meta Slider but they actually have a fairly extensive documentation section on theme integration. So major kudos for them on providing those code snippets!

As you can see we have our three sliders to choose from and now we need to determine if they are active or not. I know some will want to use is_plugin_active() but I will tell you not to. The reason for not doing so is so that you don’t load an extra file. So instead we will use some basic PHP functions to check.

function jc_get_sliders(){
	$sliders = array();
	
	if ( class_exists( 'Soliloquy_Lite' ) ){
		$sliders['soliloquy'] = 'Soliloquy';
	}
	
	if ( function_exists( 'huge_it_slider_activate' ) ){
		$sliders['huge_it_slider'] = 'Huge IT Slider';
	}
	
	if ( function_exists( 'wd_slider' ) ){
		$sliders['wds'] = 'Slider WD';
	}
	
	return $sliders;
}

I know some of you are wondering why I chose to use the class and functions I chose to check for. Those are the classes and functions those respective plugins use when they are activated. If those plugins are not active they will not exist.

Now that we have our options for plugins we can create our theme customizer options.

add_action( 'customize_register', function( $wp_customize ){
	// Set up the section
	$wp_customize->add_section( 'slider-section',
		array(
		'title' => __( 'Select a slider', 'jc-domain' ),
		'priority' => 30,
		) );
	// register the setting
	$wp_customize->add_setting( 'slider-type',
		array(
		'default' => '',
		'sanitize_callback' => 'jc_valid_slider',
		) );
	// register the setting's control but only output if those sliders exist
	$wp_customize->add_control( 'slider-type-input',
		array(
		'label' => __( 'Select the slider to use', 'jc-domain' ),
		'settings' => 'slider-type',
		'section' => 'slider-section',
		'type' => 'select',
		'choices' => jc_get_sliders(),
		'active_callback' => 'jc_sliders_exist'
		) );
	// register the setting
	$wp_customize->add_setting( 'slider-id',
		array(
		'default' => '',
		'sanitize_callback' => 'absint',
		) );
	// register the setting's control but only output if those sliders exist
	$wp_customize->add_control( 'slider-id-input',
		array(
		'label' => __( 'Input the ID of the slider you would like to use', 'jc-domain' ),
		'settings' => 'slider-id',
		'section' => 'slider-section',
		'type' => 'number',
		'active_callback' => 'jc_sliders_exist'
		) );
	
});

Great! Now you can see that I am using an active_callback for the controls. This is so that the section will not show if there are no active plugins to choose from. That means we have to create that callback. Fairly simple:

function jc_sliders_exist(){
	if ( !empty( jc_get_sliders() ) )
		return true;
	return false;
}

As you see we can utilize the first function we created that gets the sliders to our advantage. If the array is not empty we return true, otherwise we return false. Straight-forward. Now, you may notice one function we may need to create and that is jc_valid_slider. This is what will check if the option is a valid option and return it. So, let’s create that shall we:

function jc_valid_slider( $value, $control ){
	return ( array_key_exists( $value, jc_get_sliders() ) ) ? $value : $control->default;
}

Yes, you can see we are still using jc_get_sliders() to get our values. No need to create another wheel when we already have one, right?

The output

I know you are now wondering, “But Jose, how will you display the slider?” Well, let me show you how! We use get_theme_mod() and do_shortcode() with a quick check to output our slider.

add_action( 'jc_slider_area', 'jc_create_slider' );
function jc_create_slider(){
	// get the setting for the type of slider
	$type = get_theme_mod( 'slider-type' );
	// get the setting for the ID of the slider to use
	$id = get_theme_mod( 'slider-id' );
	
	// Check if we have chosen a slider
	if( !$type ){
		return;
	}
	
	echo do_shortcode( "[$type id='$id']" );
}

Great! But I know you are probably wondering why I’m using an action hook rather than creating a function and calling it. What’s super cool about using a hook is that this can be extended or removed with a child theme or functionality plugin. Super great way of making your theme extendable and child theme friendly. So, in the last step all we need to do is create that action hook.

<?php do_action( 'jc_slider_area' ); ?>

By adding that to where you want the slider to show, you can create a great hook for any theme developer to utilize.

Minor note

If you hadn’t noticed, I registered the customizer settings using an anonymous function. This will work on PHP versions 5.3 and higher so please make sure you are aware of what your environment you are developing for. So go, explore and try to break things along the way!

Two or three column section

A while back I wrote a quick and dirty tutorial on how to display more than one page. This can be done in a number of different ways. You can read about them in other tutorials and guides because this time I’ll go over another method using the WP_Query method. The codex page some really great ways and examples of using it to your advantage, I highly recommend you give it a skim and return to this.

So, on to the code!

What I’ll be using is a switch statement, an active callback, and of course the customizer API.

First we will create the settings and controls:

$wp_customize->add_section( 'demo-front-sections',
				 array(
					 'title' => __( 'Front page sections', 'text-domain' ),
					 'description' => __( 'Choose what pages to show on the front page panels', 'text-domain' ),
					 'priority' => 1,
					 'active_callback' => 'is_front_page'
				 ) );
$wp_customize->add_setting( 'col-count',
				 array(
					'default' => 2,
					'sanitize_callback' => 'absint'
				 ) );
$wp_customize->add_control( 'panel-count',
				 array(
					'settings' => 'col-count',
					'label' => __( 'How many panels on this section', 'text-domain' ),
					'type' => 'radio',
					'choices' => array( '2' => 2, '3' => 3 ),
					'section' => 'demo-front-sections',

				 ) );

// Register the page settings to get the IDs
$wp_customize->add_setting( 'page-1',
				 array(
					'default' => 0,
					'sanitize_callback' => 'absint'
				 ) );
$wp_customize->add_setting( 'page-2',
				 array(
					'default' => 0,
					'sanitize_callback' => 'absint'
				 ) );
$wp_customize->add_setting( 'page-3',
				 array(
					'default' => 0,
					'sanitize_callback' => 'absint'
				 ) );

// Set the controls
$wp_customize->add_control( 'panel-1',
				 array(
					 'settings' => 'page-1',
					 'label' => __( 'Pick what page you would like to showcase', 'text-domain' ),
					 'type' => 'dropdown-pages',
					 'section' => 'demo-front-sections'
				 ) );
$wp_customize->add_control( 'panel-2',
				 array(
					 'settings' => 'page-2',
					 'label' => __( 'Pick what page you would like to showcase', 'text-domain' ),
					 'type' => 'dropdown-pages',
					 'section' => 'demo-front-sections'
				 ) );
$wp_customize->add_control( 'panel-3',
				 array(
					 'settings' => 'page-3',
					 'label' => __( 'Pick what page you would like to showcase', 'text-domain' ),
					 'type' => 'dropdown-pages',
					 'section' => 'demo-front-sections',
					 'active_callback' => 'panel_countcheck'
				 ) );

You’ll notice I used a basic active callback for the section so that the section will only show up on the front page. You may also notice that I’ve added a callback to the third control. We haven’t created that callback so let’s do it:

function panel_countcheck( $value ){
	if ( get_theme_mod( 'col-count' ) > 2 ){
		return true;
	}
	return false;
}

Great! Now what does it do? Let’s break it down a little. So, if the first value ( col-count ) is greater than 2, then let’s show this control, otherwise we won’t. Pretty self-explanatory, right?

Great now we just need to display this on a page template, or the front page ( in our case ). We use get_theme_mod to get the values and the code will look a little like:

// get setting for how many
$count = intval( get_theme_mod( 'col-count', 2 ) );
// create an array for the new query
$ids= array();
// get the pages
$ids[] = intval( get_theme_mod( 'page-1', 0 ) );
$ids[] = intval( get_theme_mod( 'page-2', 0 ) );
if ( $count > 2 ){
	$ids[] = intval( get_theme_mod( 'page-3', 0 ) );
}

$query = new WP_Query( array( 'post_type' => 'page', 'post__in' => $ids, 'orderby' => 'post__in' ) );

switch( $count ){
	case 2:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-2">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
	case 3:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-3">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
}

Yeah, it is a little messy but we will break it down and explain what does what.

The first setting we get is the column count. You’ll see that I am using intval because we want to make sure that we are setting an integer. The value being passed from the customizer setting is an ID number that corresponds to a page ID, so we make sure that it really is an integer.

$count = intval( get_theme_mod( 'col-count', 2 ) );

Next up, we get our pages and build up the array that we will pass our new WP_Query. As you can see, we first get the first two pages and conditionally add the third if the $count is greater than 2. Remember this is the setting that the user picks.

$ids[] = intval( get_theme_mod( 'page-1', 0 ) );
$ids[] = intval( get_theme_mod( 'page-2', 0 ) );
if ( $count > 2 ){
	$ids[] = intval( get_theme_mod( 'page-3', 0 ) );
}

From there, we build up the new query. Pretty simple. We make sure that the post type is a page, and the order is maintained by what we pass it.

$query = new WP_Query( array( 'post_type' => 'page', 'post__in' => $ids, 'orderby' => 'post__in' ) );

Now we get to the switch statement! This is where the fun sort of begins.

switch( $count ){
	case 2:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-2">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
	case 3:
		while( $query->have_posts() ): $query->the_post();
			echo '<div class="col-3">';
				the_title( '<h2>', '</h2>'); the_content();
			echo '</div>';
		endwhile;
	wp_reset_postdata();
	break;
}

Okay. Let’s look over the lines a bit. As you can see we pass it the $count variable we first created, which houses the option of whether to show 2 pages or 3. We create a case for each one and as you can see the only real difference here is the class. For showing two pages it is 2-col and for the 3 it is 3-col. You can create a quick wrapper for that if you want so it can be extended by a child theme like:

function jc_classes(){
	$classes = array();
	$classes[] = 'span';
	$cols = get_theme_mod( 'col-count', 2 );
	switch( $cols ){
		case 2:
		$classes[] = 'col-2';
		break;
		case 3:
		$classes[] = 'col-2';
		break;
	}
	
	return 'class="' . esc_attr( implode( ' ', apply_filters( 'jc_custom_classes', $classes ) ) ) . '"';
}

From there we can lose the switch statement and use:

$query = new WP_Query( array( 'post_type' => 'page', 'post__in' => $ids, 'orderby' => 'post__in' ) );
while( $query->have_posts() ): $query->the_post();
	echo '<div ' . jc_classes() .'>';
		the_title( '<h2>', '</h2>'); the_content();
	echo '</div>';
endwhile;
wp_reset_postdata();

What’s really nice is you can use basic CSS to style it. A quick snippet:

.col-2 {
	float: left;
	width: 50%;
}

.col-3 {
	float: left;
	width: 33%;
}

So, go on, experiment, and fiddle around with the code a bit. Do remember I used basic things, so be sure to add the proper settings, text, and values for your needs.

Widgets and when to use them

Widgets are a great way of showing information in specified areas. Themes handle this in different locations and different ways. Some have page template with up to thirty widget areas. Yes, thirty! Sorry, felt like a salesman when I typed it out but it is true. And then you get the occasional theme that wants you to type out content. Yes. Dealing with themes and content.

The reason I’m not a fan of this is because once the theme is switched you lose that content. I know some will ask how much content is too much content? Any content that isn’t theme specific is too much.

What drives me up a wall more is when some themes bundle a widget that core is more than capable of handling. A very common one is the infamous call to action button widget. Yes. I dislike that button widget. You can use core’s text widget! Let’s see an example shall we?

$text = sprintf( __( "You can use <small>%s</small> as well as basic HTML.\n\n You just <strong>cannot</strong> use JavaScript.\n\nThis is a <em>sample</em> with auto paragraphs being used.\n\nWhat next?", 'text-domain' ), allowed_tags() );
the_widget( 'WP_Widget_Text', 
	array( 
		'title' => __( 'Using a text widget', 'text-domain' ), 
		'text' => $text,
		'filter' => true
		),
	array(
	  	'before_widget' => '<aside id="%1$s" class="widget %2$s">',
		'after_widget'  => '</aside>',
		'before_title'  => '<h1 class="widget-title">',
		'after_title'   => '</h1>',
	  ) );

Yes, it does look like quite a bit of code but there is a reason for it. The function that does the magic for us is the_widget. What’s super cool is that this means you can create an instance of a widget to create a great looking theme preview. Not only that it can serve as a bit of documentation for your theme.

Let’s take a look at another example, shall we?

The plugin I used is Feature a Page. All I did was a simple search in the plugin repository and picked one at random.

if ( class_exists( 'FPW_Widget' ) ):
the_widget( 'FPW_Widget',
        array(
            'title' => 'About our Clients',
            'featured_page_id' => '1141', // ID of page
            'layout' => 'banner',
            'show_title' => false,
            'show_image' => true,
            'show_excerpt' => true
        ),
        array(
            'before_widget' => '<aside id="%1$s" class="widget %2$s">',
            'after_widget'  => '</aside>',
            'before_title'  => '<h3 class="widget-title">',
            'after_title'   => '</h3>',
          ) );
endif;

Let’s run through the code a little. The first line checks to see if the class FPW_Widget exists. If it does, then we can run our code. As you can see the second argument we’re passing is an associative array with some settings we want our widget to display.

In this particular case the widget has some settings that we can change. They are:

$defaults = array(
	'title' => '',
	'featured_page_id' => '',
	'layout' => 'wrapped',
	'show_title' => true,
	'show_image' => true,
	'show_excerpt' => true,
	'show_read_more' => false
);

They will vary from widget to widget so be mindful of that. The codex page has the default widgets and their respective settings that you can change.

Now, what’s neat is that you can use the third argument in order to style the output of the widget. To a degree. Let’s look at the first example:

array(
	'before_widget' => '<aside id="%1$s" class="widget %2$s">',
	'after_widget'  => '</aside>',
	'before_title'  => '<h3 class="widget-title">',
	'after_title'   => '</h3>',
) );

Notice that I’m using a simple copy paste of what a register_sidebar call would do. In particular the before|after_widget, before|after_title parts. Reason being, odds are, you’ve styled the widget areas with certain CSS classes and using those instead of the default ones the_widget uses. Core markup is:

$before_widget = sprintf('<div class="widget %s">', $widget_obj->widget_options['classname'] );
$default_args = array( 'before_widget' => $before_widget, 'after_widget' => "</div>", 'before_title' => '<h2 class="widgettitle">', 'after_title' => '</h2>' );

So if you don’t define the third argument, what will be used on output is the above.

Additional notes

I used the plugin because it is a great example of how you can pull user generated content to create a widget. What’s really nice is there are several plugins that create widgets and deal with widgets. Don’t forget that you can even use a simple setting in order to create a featured content area as well. There are several themes that do this already so explore their code and learn from them.