Been a while since I wrote something. Let’s talk about some of the new stuff available in the Customizer.
Forget about some of part two
First, back in part two, I had a bit about Surfacing the Customizer. That bit is outdated now, WordPress does this for you in later versions. So, yeah, skip that.
Shiny new thing: Panels
Okay, so Panels aren’t that new. They were added in WordPress 4.0. Basically, they’re sliding containers for sections. Having trouble fitting all your settings on the screen? Group the various sections up into Panels. Panels show up as an item in the main list, and when you click the arrow next to them, the whole list glides off screen to show only those sections.
So, now we have four things: Panels, Sections, Controls, and Settings.
Panels group Sections together
Sections contain Controls
Controls are what the user changes
Settings define what the Controls change
Creating a panel is easy:
$wp_customize->add_panel( 'some_panel', array(
'title' => 'Panel 1',
'description' => 'This is a description of this panel',
'priority' => 10,
) );
All that’s new is a panel setting to tell the section to go into that panel. Simple.
Active Callbacks
One of the problems with the Customizer was that it displayed settings and showed them changing on the site to your right, but the site being displayed is the actual site. Meaning that you can navigate on it. Sometimes, the controls being shown don’t necessarily apply to the actual site that you’re seeing.
Example: If you have a control to change the color of something in the sidebar, but then are looking at a page which has no sidebar, then you have no visual feedback to tell you what the change looks like.
To fix this, “active callbacks” are used.
The active_callback is simply a new parameter that you can pass into Panels, Sections, or Controls. It can contain the name of a function, and that function will be called when the page changes. The function should return true or false (or equivalent) to indicate whether or not the element of the customizer should be shown for that page.
So, if you have a whole Panel that only make sense when the user is looking at Front Page of the site (and not an individual post), then you can do this:
$wp_customize->add_panel( 'front_page_panel', array(
'title' => 'Front Page Stuff',
'description' => 'Stuff that you can change about the Front Page',
'priority' => 10,
'active_callback' => 'is_front_page',
) );
And voila, when the user is not looking at the front page, the panel simply disappears.
You can use any of the normal WordPress Template Tags for this, or write your own function if you want to be more specific about it.
Edit: As pointed out in the comments, this will not work with ALL of the Template Tags. In particular, is_single won’t work because of the optional parameter it can take. You can define a wrapper for these methods instead, to get the same effect. Example:
function callback_single() { return is_single(); }
...
'active_callback'=>'callback_single'
...
Fun with Active Callbacks
If you do need to write your own callback function, note that the function receives the object in question when it’s called. So, if you attach an active_callback to a Panel, your function will get a argument of the WP_Customize_Panel object in question passed to it. Sections get WP_Customize_Section and such. You can use the information in these to decide whether the panel (or whatever) should be shown for that page.
So, how do we use that object? Well, you can use this to make whether certain controls show or not dependent on the values of other settings. All the various items you can use this on have a link back to the main WP_Customize_Manager. That class has a get_setting function, which you can use to determine what to do.
So, let’s make a control that causes other controls to appear, dependent on a setting.
First, let’s make a simple radio selection control:
Now, note that the callbacks are very similar. Seems like repeated code, doesn’t it? Well, it is, but remember that the $control here is the whole WP_Customize_Control object. We can use the same callback and simply check which control is calling it here instead.
So, instead of using two different callbacks, we just point our controls to this callback, which figures out what should show up for which setting. I’m sure you can simplify this further, depending on your particular needs.
One more thing: Customizing the Customizer
Not everybody likes the style of the Customizer. Maybe it clashes with your theme. Maybe you just want to tweak it a bit. Maybe you dislike that gray background color, and a more soothing blue would go better for your theme.
You can enqueue whole extra CSS files instead, if you like. Or, if you have special needs for javascript in some of your controls, and there’s libraries necessary to implement them, then you can enqueue those libraries here as well.
One of the easier to understand vulnerabilities is the CSRF. It’s also one of the most common issues we see in plugins and themes, because people rarely think about it.
Imagine that I have a form that takes input, like so:
Now, that’s a simple form (and missing a submit button to boot), but you get the idea. It takes a text input. Presumably, something on the other end (at /example.php) processes that input, saves it in a database, something like that. Easy.
First question: Is this necessary?
The main question I see asked when this concept is explained to people is “why is this necessary?”. Some people believe that since you have to be logged in to access admin screens in the first place, then you can’t get to the forms and submit them. Why have all this protection and checking for a form submission when the form is hidden behind a login screen?
What you need to understand is the difference between “authority” and “intent“.
Authority
In real world cases where we are processing that input, we generally want to limit who is allowed to submit that form in some way. A plugin will want to only allow admins to change settings. A theme will only want to allow site owners to adjust the display of the site. Things of that nature. For these cases, we use methods of authentication.
There’s several ways to do this, we can check the current_user information. WordPress has capability checks for users to know what they are and are not allowed to do. When we check these, we’re verifying authority. Making sure that the user is allowed to do these things.
But something else that we need to check which most people don’t think about is intent. Did the user actually intend to submit that form, or did their browser submit it for them automatically, perhaps without their knowledge?
Examine that form again, and consider what would happen if you were to visit a webpage, anywhere on the internet, that contains this:
Now, you might be thinking that this is a rather contrived example, and you’d be right on that score, but it serves to demonstrate the point. Your browser loads this URL and that is the equivalent action to submitting that form, with “pwned” as the text in question.
Here’s the kicker, all those authority checks do us no good in preventing this. You actually do have the authority to submit that form, and your browser, using your authority, just submitted it for you. Pwned, indeed.
(For those of you thinking “just use POST forms”, consider that javascript can submit POST forms. So that’s really no help.)
Intent
What we need is to verify intent. We need to know that the user submitted that form, and not just the browser doing it for them automatically.
WordPress used to do this (a looong time ago) using the referer. For those who don’t know, referer is a URL passed by your browser to indicate where a user came from. So one could check that the referer says that the form was submitted from the form’s page and not from some other page on the internet. The problem is that referer is not reliable. Some browsers have the ability for script to fake the referer. Firewalls and proxies often strip the referer out, for privacy concerns. And so forth.
Nonces
WordPress now does this using nonces. A nonce is a “number used once” in its purest form. Basically, it’s a one-time password. When we generate the form, we generate a number. When the form is submitted, we check the number. If the number is wrong or missing, we don’t allow the form to be submitted. A script cannot know the number in advance. Other sites cannot guess the number.
Now, technically, WordPress doesn’t use real nonces, because they’re not “used once”. Instead, WordPress nonces revolve on a 12 hour rotating system (where 24 hours are accepted). For any given 12 hour period, the nonce number for a given action will be the same. But it’s close enough to a real nonce to eliminate the issue, but notably it’s only for the issue of verifying intent. Don’t try to use WordPress nonces for anything else. 🙂
So, when we generate a form, we generate a nonce. This nonce is based on five things: site, user, time, the action being performed, and the object that the action is being performed on. Changing any of these gives us a different nonce.
Let’s say I want to delete a post. To do that, I need to know the nonce for deleting that specific post, as me, on my site, within the last 24 hours. Without that nonce, I cannot perform the action. More importantly, in order for somebody to “trick” my browser into doing it for me, they need to get that specific nonce and get my browser to load it within 24 hours. Tough to do. And even if they pull it off, they only have been able to perform that very specific action, the nonce obtained is useless for any other purpose. They don’t get any form of full control via this manner. They can’t make my browser do anything on mysite that they don’t have the nonce for.
Using nonces
So, let’s get down to brass tacks. Generating a nonce in WordPress is easy and can be done in many different ways depending on your particular needs. You might want to protect a simple link, or you might want to protect a form, or you might even need to protect a javascript ajax call.
Protecting a link can be done with wp_nonce_url(). It takes a URL and an action and adds a valid nonce onto that URL. It works like this:
Here, we’re taking some URL, and adding a nonce onto it for a specific action on some specific object. This is important, actions and objects need to both be specified if there is some object being referred to. An example might be a link to delete a specific post. Such code would look like this:
wp_nonce_url( $url, 'trash-post_'.$post->ID )
The action is “trash-post” and the post being trashed has its ID number appended to that action. Thus, the nonce will let you trash that post and only that post.
On the other hand, maybe we have a form that we need to protect instead. Inside that form, we can add something like this:
wp_nonce_field( 'delete-comment_'.$comment_id );
This is the nonce for deleting a comment. It outputs a couple of form fields, like so:
The value for the nonce will be specific to deleting that comment, on that site, by that user.
Sometimes we just need to generate the nonce directly, in no specific format. One case might be for an AJAX type call, where the data is being submitted by jQuery. In such a case, you can use the wp_create_nonce function to get just that nonce value, like so:
wp_create_nonce( 'action_'.$object_id );
For AJAX requests, you’ll want to include that nonce value in the submitted data with a name of “_ajax_nonce”. Why that particular name? Because it’s what WordPress checks when verifying the nonce. Speaking of verification:
Verifying nonces
Generating these numbers is no good if you don’t check them as well. Fortunately, WordPress makes this easy. There’s two functions to verify incoming nonces.
check_admin_referer( 'action_'.$object_id );
The name of the function refers back to the time before nonces, when this function call was checking the referer value from the browser. Nowadays, it checks nonces instead. If the _wpnonce sent back in the form does not match the action and ID here, then this function stops further processing. This is the cause of the “Are you sure you want to do this?” screen that is sometimes reported by users. To avoid getting this screen, the nonce being checked has to match.
An alternative to checking forms or links is checking ajax requests, which is why we have this function:
check_ajax_referer( 'action_'.$object_id );
This performs the same basic check, but if it fails, it returns a simple “-1” response and then halts processing. Your AJAX javascript code can recognise that response and take appropriate action based on it.
In either case, if the nonce fails, the script exits. No action is taken. The form is not processed, the post not deleted. That’s the sort of check you need to prevent CSRF attacks.
Bottom Line
If you have a plugin or a theme or any type of code that “does something” in WordPress, then you need to protect that action with a nonce. If you’re not protecting it with a nonce, then it’s possible for somebody else to trick your browser into performing that action on your behalf.
Also, note that it’s not enough to just name the action. You generally are taking action on some specific “thing”, and the ID of that thing needs to be included in your nonce as well. The more specific the action, the better.
Any form, any action, no matter how much “authentication” you have on checking it, can be exploited, because you’re not really authenticating the “user”, you’re authenticating that it’s coming from “the user’s browser”. You need to have something else that changes regularly, so that you can verify that the user did indeed load that particular form and submit it relatively recently, and thus probably intended to perform that action.
Nonces are easy to implement. So do it already. We have enough plugins not doing it that this clearly needs to be said. 🙂
You know, when some people are asked to do a presentation on a subject, they start by thinking about what they’re going to say, how they’re going to say it, and what their presentation will contain.
Me, I just start writing code.
I was asked to present at WordCamp Seattle, on the specific subject of the GPL. Talking about licenses is pretty dry stuff, so I came up with some ideas and such and put them down and built a presentation. No problem. But naturally, I wanted to use WordPress to present it.
I’ve tried this sort of presentation-theme idea a couple years back, and didn’t really get anywhere good. HTML wasn’t up to the task at the time, not really. But in my searching for this again, I ran across the Google IO 2012 slides template.
It’s a neat template. Does some very cool stuff. HTML5, CSS3, clever Javascripty goodness. Bit annoying to adjust though, and very hardcoded. So, I turned it into a WordPress theme instead.
I call it “Slides”, because I’m bad at naming things.
If you want to skip straight to the download, you’ll find it at the bottom of the post, but I encourage you to read first, because if you just install it on an existing WordPress install, you’ll find your site to be instantly broken.
I’m not a fan of the color orange. Dunno why. I prefer soothing and relaxing colors, like blues and greens.
But the new Twenty Thirteen theme for the next version of WordPress is very, very orange.
Since I like to run the default themes over on my other site, this clearly could not stand.
So, I did a palette swap. Basically, I took the three header images, and swapped the Red and Blue channels, leaving the Green channel alone. Easy enough to do in Photoshop.
Then, I made a child theme, and put some minimalist code in the functions.php file to fiddle with the default header images to use the ones from my child theme instead of the normal ones. Finally, I did a search and replace for all the color references in the style.css file, swapped the R and B values in them, then put them in my new style.css file.
The result you can see over on my other blog. Yes, I know I don’t write often enough. Hell, I’ve been busy.
Child themes are fun to mess with. Here’s a copy if you want it for anything.
Okay, a quick one today. Let’s make a custom control for the customizer.
Back in the first tutorial, I talked about the various controls available in the customizer. Specifically I mentioned image handling, color wheels, text boxes, radios, dropdowns, and checkboxes.
Let’s try a new one? How about a textarea? It’s not in the core code, but it’s easy enough to add one.
Create a Class
So first, we have to create our class. Now, where we create this class is important. Specifically, we have to create it in the function called by the customize_register action. You remember that, right? It started like this:
add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
// ... do stuff ...
The reason we have to create our class in here is because we need to make our new class extend the built in WP_Customize_Control class, and that class only gets loaded and defined when we’re actually using the customizer. An alternate means of doing this would be to wrap the class definition in an “if (class_exists(‘WP_Customize_Control’))” statement, if you prefer to not have your classes defined inside a function. Personal preference, I don’t think it makes a difference either way.
So, here’s our textarea control. All we’re doing is to override the render_content() function and make it display a textarea.
class Example_Customize_Textarea_Control extends WP_Customize_Control {
public $type = 'textarea';
public function render_content() {
?>
<label>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
<textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
</label>
<?php
}
}
You can see how simple it is to do, really. We just output a span with the value from $this->label for the name displayed above the textarea, then output the textarea itself.
Note that the textarea has no “name” parameter. It doesn’t need one. The $this->link() function outputs the information for the customizer script. Specifically, it will create a “data-customizer-setting-link” attribute, to link the textarea to the proper setting it’s controlling.
Now, we just have to use the new control.
Add a setting and control
Let’s go back to the theme demo I used in the second customizer tutorial post, and add a new setting and control to demonstrate this:
$wp_customize->add_setting( 'textarea_setting', array(
'default' => 'Some default text for the textarea',
) );
$wp_customize->add_control( new Example_Customize_Textarea_Control( $wp_customize, 'textarea_setting', array(
'label' => 'Textarea Setting',
'section' => 'themedemo_demo_settings',
'settings' => 'textarea_setting',
) ) );
Nothing complicated there. We create the setting, then we create our control, using the new class we made for this purpose earlier.
Use the setting in the theme
Now let’s add to that index.php file I made in the theme demo to show the results of our work.
And that’s pretty much that. We now have a textarea control, and changing/saving results in the setting changing as well.
You can extend this further to use postMessage for real-time changing of settings, if you like.
Custom controls using complex javascript and such can be done as well. Examine the core WP_Customize_Color_Control, which uses the farbtastic Javascript for the color wheel. That one has special JS in the customize-controls.dex.js file to handle receiving the input and passing it along to the customizer JS. Look for “api.ColorControl” and how it gets the setting from the HTML and sets it. I’m not a JS guru, that sort of thing is slightly outside my own scope. 🙂
Any ideas for other controls that themes might need? Leave a comment, maybe somebody has a solution.
Last time I wrote about using the Theme Customizer to supplant/add to your existing options. But what if you’re writing a new theme entirely?
Do you even need an options page?
How many options does your theme have, anyway? Would it not make more sense to eschew those complex options pages in favor of just allowing the user to do it all “live”? With the Theme Customizer, this becomes entirely possible. As an added bonus, it also gives us a really handy use for the theme_mod system.
Step 1: Surfacing the Customizer
One thing I don’t like about the theme customizer is how hidden it is. It’s in the Themes selection space, under the strangely worded “Live Preview” option. Let’s bring that to the forefront and make it more visible for our example theme. In our functions.php file:
add_action ('admin_menu', 'themedemo_admin');
function themedemo_admin() {
// add the Customize link to the admin menu
add_theme_page( 'Customize', 'Customize', 'edit_theme_options', 'customize.php' );
}
There we go. Now we have a “Customize” link in the Appearance menu that loads up the customizer. Nice.
(Note, using the “customize.php” link works with the currently active theme only. Adding ?theme=themedemo to it would allow links to customize non-active themes, but this makes no real sense in the theme functions.php file of a theme. But if you were doing a plugin that needed to load the customizer, that might be good to know.)
Don’t do this anymore, kids. WordPress brought the Customize link to the surface in a later version.
Step 2: Adding some options
Let’s add some simple options to the theme customizer. How about a text field and, say, a color picker. Why not?
We now have “some_setting” and “some_other_setting”. You can tell that I’m being very creative with my naming scheme here. 😉
Note that I didn’t define the “type” for these settings. This means they’ll be the default type, which is “theme_mod”, and that’s perfect for this case. Since we’re providing no other way than the customizer to change these settings, then it’s nice and easy to use them.
The header and footer are pretty standard. Nothing special. You can find them in the download. What we’re really concerned with here is how the theme uses the settings themselves.
Notice the use of get_theme_mod. It’s pretty darned easy to use, really. It just gets the settings and uses them however the theme needs to. For this demo, I’m just outputting their contents for demonstration purposes. I also added in a non-existent setting to show that it works and outputs the default value when nothing is set for the theme in the theme_mod system.
The nice thing about theme_mod is that it automatically stores the information in a nice packed way, unique to the theme itself. If you have multiple copies of the same theme on the site, but with different names, each will have its own settings. Easy and handy.
Step 4: There is no step 4.
Seriously, that’s it. You can go further and make the settings work “live” using the postMessage methods I explained in the previous post, but for the most part, there’s nothing more to do. This is a simple and easy way of making settings, using them, and not worrying about complex options pages, settings in the database, where they’re stored… Why do all that extra code if you don’t have to?
Here’s a link to a working theme using the above concepts. For fun, it also supports custom background colors. 🙂
Note: Everything I’m talking about here, including the code, is in beta mode. It will be subject to change. I’ll update this post after release to fix any code changes that may occur between now and then. I’m releasing this post now so that theme authors can start looking at their themes and thinking about how they might want to change the way they do options pages.
So, WordPress 3.4 has this nifty new feature you can find on the main Theme selection page. It’s a link next to each theme labeled “Customize”. This is the new Theme Customizer, and it’s way cool.
In fact, you can’t see what it does with a simple picture, so here’s a video. It’s available in HD if you want to go full screen. 🙂
So, now you know what it does, and if you’re a theme author, you’ve probably just gotten some great ideas. Here’s how you can implement those ideas in your theme.
First, note that if you already support the built in Custom Header and Custom Background functionality the WordPress core provides, then those will magically show up and work in the theme customizer. No extra code needed on your part.
Existing Options
Now, the first thing you’ll probably want to do is to take note of how your existing settings in the theme work. You have three main options for theme settings, realistically. I’ll go over them briefly.
1. “Theme mod”. This uses the set_theme_mod and get_theme_mod functions. It’s rare that themes actually use these since I wrote about the Settings API, but it is there and if you use these normally then it is supported by the Theme Customizer (in fact it’s the default).
2. Individual Settings. If you store your theme’s settings in the options table as individual rows, one per setting, then that works fine with the customizer. This is not the preferred way of doing things in themes, however, and not the most common. Still, some themes do this, so if you’re one of them, it’s supported as well.
3. Serialized Settings. This is the way I explained in my Settings API Tutorial and the method recommended by the Theme Review guidelines, as well as the way Chip described in his own tutorial for theme settings. Essentially, you store your settings in an array, then store that array using set_option or get_option, as one row in the database. This method is supported and it’s the way I’ll primarily cover in this article. I’ll briefly mention the other two methods when appropriate.
Once you know how your settings are stored, then you’ll know what to fill in at certain spots in the code. More on this when we get to it.
Object Orientation
Now, the Theme Customizer is very object oriented, and while you don’t necessarily need to understand this to implement the basics of it, you might need to understand it if you’re going to make something completely custom. Just a warning.
First, we’ll look at the left hand side of the customizer screen. Notice that the left hand side is divided into sections. Actually, that’s their name: WP_Customize_Section. In each of these sections is one or more controls; or rather, WP_Customize_Control. Finally, each of these controls one of more settings on the page: aka WP_Customize_Setting.
The Sections organize the controls. The Controls get input and pass it to the settings. The Settings interface with your existing options in the theme.
To make new stuff here for your own custom options, you need to know where to add it. That place is the customize_register action hook.
add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
// ... do stuff ...
The function gets a parameter of the main $wp_customize object. This is the interface point where you will do everything like adding sections and controls and such.
Sections
So, first thing to do is to add a section. Here’s one way to do it:
The first parameter is a unique ID for the section that you’ll need later (when you’re putting controls into it). The second parameter is an array of options for the section. Sections don’t have a lot of options, really. You can give them a title, you can give them a “description” if you need some explanatory text in them. The priority setting determines their order in the list.
You can also give sections a “capability” if you have a special case. Generally speaking, most sites require the “edit_theme_options” capability to have users edit this sort of thing, and this is the default capability that the sections use. However, if you have options that anybody can edit, or which should only be managed by administrators, changing this capability will prevent the section from appearing to users who can’t change those settings anyway.
One final thing you can add to a section is a “theme_supports” option. This will make the menu not appear unless the theme supports something. If you’re putting this code in a theme itself, then you already know what the theme supports, so it doesn’t make much sense. The core uses this to not show the header and background options if the theme doesn’t support them.
Settings
Next, let’s configure some settings. Yes, the settings, not the controls. See, the controls need to know what settings they’re changing, so we have to attach the settings up first.
In this case, I’ve declared that the setting I’m interested in is in an option, the option is named “themename_theme_options” in the database, and it’s serialized, and the actual array key in there is “color_scheme”. Remember that talk we had before about the Settings API and how you store your settings? This was method 3.
This setting basically tells the theme customizer where the option is stored, and how to change it’s value so that your theme displays with the changed option.
Here’s the good bit about this: You’re telling the theme customizer where the option is. You don’t have to change the way the existing option works at all.
You already have a theme options page, right? So somehow, you’re saving those options. And in the theme, it’s reading those options using get_theme_mod or get_option, right? The way the theme customizer works is that it intercepts that call using a filter, changes the option for the previewer case only, and then passes the new option along to the theme. So the theme has no idea that the value it’s getting isn’t in the database, but one the user just selected. That’s the magic trick and why themes don’t have to dramatically change to support this sort of thing. All they have to do to make custom sections is to tell the theme customizer code what options they’re using and how, and it changes those options directly for the previewer.
(Note of clarification here: The “default” setting above should be a default value, not the current value. The difference is a subtle one, but the point is that you don’t actually need to get the current value of the option from the DB and put it in here. The WP_Customize_Setting takes care of all that jazz for you. The “default” is what should be used if the value doesn’t exist in the DB at all.)
There’s one more bit to the add_setting call that we’ll come back to later when I get around to explaining postMessage.
Controls
Finally, we come to the controls. Controls can look one of a lot of ways, obviously. The simplest controls are just checkboxes, or text fields. However, colors are something that change a lot, so there’s color wheel controls too. In fact, WordPress defines a number of possible controls. Let’s go over a few:
Pretty simple. It’s referencing the section it’s in, the setting that it’s going to change, and then it has the radio type and the list of choices along with their associated values.
How about a checkbox instead? This one comes straight from core:
The default type of control is actually type = ‘text’, and it creates a text box control. One more type of control is the “dropdown-pages” type, which creates a dropdown list of the WordPress Pages.
But that’s not all. There’s actually several more, but because they’re so custom, they’re declared differently. Here’s where we get all object oriented on ya…
Whoa, what’s with the new class? The WP_Customize_Color_Control is a class that is extending the built in WP_Customize_Control class. It adds the color wheel jazz to places where color selection is needed. Note that the class is being created here with new, and so it has to get the $wp_customize passed to it directly, so it knows where to hook in. (Note: This may change before final 3.4 release.)
Other controls of note:
WP_Customize_Upload_Control – This gives you an upload box, for allowing file uploads. However, you probably won’t use this directly, you’ll extend it for other things… like:
WP_Customize_Image_Control – This gives the image picker and the uploader box. It extends the upload controller. You can see it in action on the custom background piece, where a user can upload a new file to be the background image.
WP_Customize_Header_Image_Control – Because of the resizing action of the header piece, it needs a bit of special handling and display, so the WP_Customize_Header_Image_Control extends the WP_Customize_Image_Control to add that functionality. You can see it in action on the custom header piece, where a user can upload a new file to be the header image.
So, the way to create a custom controller to do whatever you want is to make a new class of your own which extends WP_Customize_Control and adds the bits you want. How to do that is a bit complex, so I’ll save that for another tutorial. For now, you’ve got image handling, color wheels, text boxes, radios, dropdowns, and checkboxes. I think that should be enough to get started with.
End of tutorial?
Not quite. Everything I went over above is enough to add new sections to the customizer, put controls in them, and then to have the preview show your changes after a slight delay when the page refreshes. All you have to do is to call those functions with the proper parameters, in the proper place, and it’ll work.
However, note that I said “when the page refreshes”… C’mon… this is the year 2012. We don’t have flying cars, and we still have to wait a whole second or two?
Nope.
Enter postMessage
Back when I mentioned the $wp_customize->add_setting function call, I mentioned “one more bit”. That one more bit is the option called “transport”.
Transport defines how your setting change gets from the place where you changed it into the preview pane. The default setting for this is “refresh”. An alternative setting is named “postMessage”.
The postMessage transport makes it such that the setting is instantly sent into the other frame, where javascript can adjust the page on-the-fly using this new information.
An example:
Let’s say we have a setting to change the colors of the titles. All the titles on the page are in some tag that has a class of posttitle, perhaps. The option normally just saves the HTML color chosen, then outputs some inline CSS in the header.php to basically do this:
.posttitle {
color: #abcdef;
}
Or whatever the option actually is for that color.
We have hooked our setting to that option, and hooked our WP_Customize_Color_Control up to it, and now when we change it, it works and we can see the color change. Note that this is easiest to do with already working customizer options, so the best way to do it is to get it working normally first, then add on this next bit.
Now, we have the working option in the customizer, so to take away that refresh delay, we’ll add this new option to the add_setting call:
'transport' => 'postMessage',
This tells the customizer that the setting will be sent directly to the frame via javascript. However, for that setting to work, we need javascript in the frame itself to receive it.
So, back in our main function… remember that? It started like this:
add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
// ... do stuff ...
Right at the end of that function, we’re going to add this code:
This is going to add a new function call to our preview frame’s footer. It only gets added with the preview frame, so the live site and others won’t see it, because they don’t need to see it. This is where we’re going to output our javascript to make things happen in real-time.
Here’s our function:
function themename_customize_preview() {
?>
<script type="text/javascript">
( function( $ ){
wp.customize('setting_name',function( value ) {
value.bind(function(to) {
$('.posttitle').css('color', to ? to : '' );
});
});
} )( jQuery )
</script>
<?php
}
As you can see, it just outputs a bit of javascript. This code won’t change much, ever, so let’s go over just two pieces of importance:
‘setting_name’ is the name of the setting, as added by the $wp_customize->add_setting call.
The entire line starting with jQuery(‘.posttitle’) is our custom bit of code. It gets the “to” variable, which will be the color chosen by the user, and it sets the posttitles on the page to have that color, using the css modifying functionality of jquery.
Those are the only two bits you need to change, really. The rest is pretty copy-pasta. For each real-time setting, you can dupe this bit of code in the script.
Here’s another thing: You can change pre-existing refresh settings to be postMessage ones. Take the Site Title and Tagline elements in the Header section, for example. These are refresh settings, and the reason they are is because each theme implements them differently. There’s no way for the core to know the javascript code needed for any particular theme.
But if you’re a theme author, then you’re not writing for a generic theme. You’re writing for your particular theme. You know how the site title and tagline are displayed. There’s no reason you can’t make those update in real time. And while you’re at it, the header_textcolor setting can be real time too, since you know the theme code.
In your main function again, add these three lines of code:
That changes the transport on those core settings to be postMessage. Now you need to add the javascript code to actually do the refreshing in your theme. Here’s an example of TwentyEleven doing this (with the patch I wrote for it):
function twentyeleven_customize_preview() {
?>
<script type="text/javascript">
( function( $ ){
wp.customize('blogname',function( value ) {
value.bind(function(to) {
$('#site-title a').html(to);
});
});
wp.customize('blogdescription',function( value ) {
value.bind(function(to) {
$('#site-description').html(to);
});
});
wp.customize( 'header_textcolor', function( value ) {
value.bind( function( to ) {
$('#site-title a, #site-description').css('color', to ? to : '' );
});
});
} )( jQuery )
</script>
<?php
}
For the blogname, it changes the HTML inside the “#site-title a” link. For the description, it changes the tag with #sitedescription. For the color of those, it simply targets both of them and alters their CSS.
Core has to try to be generic across all themes. But themes have more knowledge of how they work and can change things to target themselves in better ways. A theme adding controls knows what those controls change, so if it’s something simple like CSS or even something more complex like HTML, if you can write javascript code to make that modification in real time, then you can use postMessage and eliminate that refresh delay.
Hopefully this explains some of the theme customizer. Was it as clear as mud? Take a look at my patch to Twenty Eleven to add some of the theme options from its existing options screen into the customizer. You can find it on this ticket: http://core.trac.wordpress.org/ticket/20448.
In trying to figure out what to talk about at WordCamp Atlanta, I remembered a question put to me in WordCamp Birmingham. The question was how can a theme developer easily make a plugin-dependency in their theme?
I wrote some code to do this sort of thing, just as an example/test/demonstration, but then after looking over the schedule, I found that Thomas Griffin had beat me to it. After looking over his slides and having him walk me through his code, I realized that his solution was much more fully featured than mine, so I’m glad I didn’t present anything on this topic. (I ended up just doing an answer session where I tried to answer any question put to me, and frankly that was much more fun than having slides, so I’m probably just going to do that from now on.)
However, his solution is highly complex. The class he came up with is well done and fully-featured. He has capabilities for making notifications in the header space on the admin section, lightbox popups, bulk installs, forced activation, custom skinning, etc. It’s a big thing. While that’s great for a lot of people in terms of having code you can just drop-in and use, I thought that it doesn’t do much to teach how one can DIY it.
See, the code I wrote was tiny. It basically just provides some minor functionality to show a theme author how to detect installed plugins, how to detect when they’re active, how to build install and activate links, etc. It doesn’t do any pretty stuff. No custom skinning. No lightbox popups. All these things are possible, but if somebody hands you a hunk of library code to do them, then you know how to use that library, not how it works. I dislike using libraries for this reason.
So here’s the small class I wrote to do the same sort of thing, but in a very bare-bones style.
/*
Simple class to let themes add dependencies on plugins in ways they might find useful
Example usage:
$test = new Theme_Plugin_Dependency( 'simple-facebook-connect', 'http://ottopress.com/wordpress-plugins/simple-facebook-connect/' );
if ( $test->check_active() )
echo 'SFC is installed and activated!';
else if ( $test->check() )
echo 'SFC is installed, but not activated. <a href="'.$test->activate_link().'">Click here to activate the plugin.</a>';
else if ( $install_link = $test->install_link() )
echo 'SFC is not installed. <a href="'.$install_link.'">Click here to install the plugin.</a>';
else
echo 'SFC is not installed and could not be found in the Plugin Directory. Please install this plugin manually.';
*/
if (!class_exists('Theme_Plugin_Dependency')) {
class Theme_Plugin_Dependency {
// input information from the theme
var $slug;
var $uri;
// installed plugins and uris of them
private $plugins; // holds the list of plugins and their info
private $uris; // holds just the URIs for quick and easy searching
// both slug and PluginURI are required for checking things
function __construct( $slug, $uri ) {
$this->slug = $slug;
$this->uri = $uri;
if ( empty( $this->plugins ) )
$this->plugins = get_plugins();
if ( empty( $this->uris ) )
$this->uris = wp_list_pluck($this->plugins, 'PluginURI');
}
// return true if installed, false if not
function check() {
return in_array($this->uri, $this->uris);
}
// return true if installed and activated, false if not
function check_active() {
$plugin_file = $this->get_plugin_file();
if ($plugin_file) return is_plugin_active($plugin_file);
return false;
}
// gives a link to activate the plugin
function activate_link() {
$plugin_file = $this->get_plugin_file();
if ($plugin_file) return wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin='.$plugin_file), 'activate-plugin_'.$plugin_file);
return false;
}
// return a nonced installation link for the plugin. checks wordpress.org to make sure it's there first.
function install_link() {
include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
$info = plugins_api('plugin_information', array('slug' => $this->slug ));
if ( is_wp_error( $info ) )
return false; // plugin not available from wordpress.org
return wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $this->slug), 'install-plugin_' . $this->slug);
}
// return array key of plugin if installed, false if not, private because this isn't needed for themes, generally
private function get_plugin_file() {
return array_search($this->uri, $this->uris);
}
}
}
Obviously, for theme authors wanting to do something, they’re going to want to make much prettier means of displaying things and installing things. Thus, this code is meant as an example, to show the basics of how to detect such things.
So, use it directly if you like (it works), but more importantly, if you want to put plugin dependancies in your theme, then I suggest reading it and figuring out how it works instead. Then you can see how plugins can be detected and how to build simple install and activation links.
(BTW, note that I used the slug and the PluginURI for a reason. Plugins should be using a unique URL for the plugin in their code, and that URL is very likely to be the most unique thing about the plugin, and therefore the best way to check for a plugin already being there or not. Slugs can be duplicated by accident or design, but URLs are generally going to be unique and specific to a particular plugin.)
In the WordPress world, security is always a prime concern, and for obvious reasons. It’s a major target for spammers, what with 30 million sites and what have you. So there’s a lot of security plugins to do scanning on your files, there’s file monitor plugins which work by simply noticing changes to the files of any sort, we do scans in the theme check process, etc.
I’ve gotten a few responses back to some of my malware related posts asking why WordPress doesn’t check for this sort of thing in the core code. Why can’t WordPress check for the existence of “eval” and such in a plugin before it runs it? Well, I’ll show you.
Securi covered the “Pharma” attack several months ago, but nobody seemed to notice the important bit of code that shows why WordPress can’t do scanning in core. Fact of the matter is that the hacks have already gone well beyond scanning for strings and such.
Take this code for example:
<?php $XZKsyG='as';$RqoaUO='e';$ygDOEJ=$XZKsyG.'s'.$RqoaUO.'r'.'t';$joEDdb='b'.$XZKsyG.$RqoaUO.(64).'_'.'d'.$RqoaUO.'c'.'o'.'d'.$RqoaUO;@$ygDOEJ(@$joEDdb(long long string here)..
What does that do? Well, in short, that’s an eval(base64_decode()); Here it is again, broken down with newlines and such:
$XZKsyG='as';
$RqoaUO='e';
$ygDOEJ=$XZKsyG.'s'.$RqoaUO.'r'.'t';
$joEDdb='b'.$XZKsyG.$RqoaUO.(64).'_'.'d'.$RqoaUO.'c'.'o'.'d'.$RqoaUO;
@$ygDOEJ(@$joEDdb(long long string here)..
Those third and fourth lines are important, so lets fill in the two variables there with the ‘as’ and ‘e’ from above it:
And we have “assert” and “base64_decode” once again. The assert function will also evaluate strings as PHP code, BTW. It’s really just an eval in another form.
The final line uses something about PHP that some people may not know. If I have a variable with a string in it, then I can call a function with that strings name by using the variable instead of the function name. In other words, this works:
function do_something() { }
$var = 'do_something';
$var();
Now tell me, how you gonna scan for something like that?
Determining whether a piece of code is malicious or not is basically equivalent to the halting problem. You can’t do it programmatically. Not really. If WP added code to the core to try to detect and stop this sort of thing, the spammers would simply modify their code so that the core couldn’t detect it anymore.
Why get into an arms race? It’s better to concentrate on making WordPress itself secure and to try to educate both users and hosts about good security practices. Most hacked sites get hacked via insecure server configurations, not through WordPress itself.
So scanning is pointless. So why do we still do it for theme check and such? Because not all malicious code is as cleverly written, and so some basic scanning is indeed somewhat effective. And the goal there is simply to weed out the problems. All of the WordPress.org theme checking is done by human eyeballs, the scanning tools just ensure a minimal level of theme capabilities and make pruning that much quicker.
Saw this post about Chrome voice searching in HTML forms on Google’s blog today. Very cool, so I had to give it a try. If you check the “Search” box in the upper right corner of the page, you’ll see a little icon (if you’re using a dev version of Chrome). Click it to do a search-by-voice.
What I didn’t expect was how totally easy it is to implement. Seriously, it’s less than a line of code.
Example. Say your search box (possibly in your theme’s searchform.php file) looks like this:
All you have to do is to add some bits to the input element box. Specifically, you add x-webkit-speech speech onwebkitspeechchange=”this.form.submit();”. That’s it. Seriously:
Note that this won’t validate, if you care about that sort of thing. Works fine though.
You can do a whole lot more with Javascript and events and translations and multiple choices and such, if you’re thinking of developing something cool with it. I’m just shocked and amazed that this is already in my browser and I had no idea it was there. Very cool.