When I go to WordCamps, I get this question a lot: “Why do you have the PHP Code Widget still in the directory?”
There’s a good answer for that, but first let me explain why I made the thing in the first place.
If you examine the history of that plugin, you’ll find that it was submitted almost 10 years ago. Back then, widgets were new. Most people using WordPress had hardcoded sidebars in their themes. Changing the sidebar meant changing the theme. Widgets aimed to replace that with draggable objects. The Widget plugin was still a plugin, and not in core, but headed there.
The PHP Code Widget was created to make it easy and simple and fast to migrate from a hardcoded sidebar to a widget based one. You could take your existing code in the sidebar file, paste it into the widget, and then you had a movable widget that you could easily use.
Obviously, this was not meant for long term usage. The goal was to get widget support rapidly in your theme, with the expectation that as new widgets came out, you could replace your old code with newer, shinier, well supported, widgets.
The reason the plugin is still in the directory is because it still fills a need for some people. If I removed it, then they would fulfill that need in worse ways. It does not take much searching to find snippets of code, with bad advice saying to just pop it into your theme’s functions.php file, and voila, now all your Text Widgets run PHP code. That snippet actually exists. It’s a terrible idea, for obvious reasons.
The PHP Code Widget is less terrible than the alternatives.
But it’s still terrible.
And yes, it bothers me that it is one of the top 150 plugins. Storing PHP code in your database and then running it is just dumb. Don’t do that. Code should live in the right place, and that place is not the database.
So, in an effort to reduce the usage of the PHP Code Widget, here’s one way to stop using it, if you still are.
Getting rid of the PHP Code Widget
Step 1:
Get the PHP Code that you are using from the Widget, copy it into a text editor, save it somewhere for safe keeping.
Step 2:
You’re going to make a new plugin. You can call it whatever you like, but I recommend naming it specific to the site you’re making it for. If I was making a plugin for this site to hold widgets, then I’d call it “Ottopress Widgets” or something to that effect.
How to make a new plugin:
(Note: You can use Pluginception for this instead, if you like. That one I’m not ashamed of, it’s a very handy tool.)
a. Make a directory in /wp-content/plugins named after your plugin, like /wp-content/plugins/ottopress-widgets
b. Make a PHP file in there named the same. Like ottopress-widgets.php.
c. Edit that file, and add this header to the top of it:
<?php
/* Plugin Name: Ottopress Widgets*/
Lovely. We’ve made a new plugin. It doesn’t do anything, yet, but here’s some more code to add to the plugin. This is largely copy-paste, and then you edit it to fit your specific circumstances
I named this widget “Ottopress Widget” by way of example. In the first few lines of code, you’ll want to change these to your own naming scheme. It’s important that names be unique, which is why I recommend naming things using your site’s name. Unlikely for there to be interference that way.
The $class and $name variables you should also change. The class is used in the HTML that the widget produces, so you can refer to it via CSS. The name is simply used for display purposes on the widgets editing screens.
Step 4:
Finally, the meat of the code you want to edit is here. I’ll point it out specifically.
This is the code that shows the widget on your site itself. Now, this one is just hardcoded to show the normal before and after code (these are set by the theme, so these should always be there), and then it has a little hardcoded bit there where it echo’s out a title and a div that says “Here’s my Custom Stuff”.
If you’re migrating from the PHP code widget, well, here’s where you migrate it to. You can drop your code from the PHP Code widget here and, you know, do whatever you were doing in the widget before, just now in an actual custom widget, in your own custom plugin. No more storing the code in the database. Just activate the plugin and replace the PHP Code widget with this one.
If you need more widgets because you were using it in multiple places, then simply repeat the process. Paste that whole class in there, only give it a different class name and other info, then put in your other code. You can have as many widgets as you like, they just have to all be named differently. Simple.
Note that this widget has no settings screen of any kind. Why would it? You’re controlling the code directly, no need for settings, presumably. If you want to go on and make your widget smarter and more complex and have settings, well, there’s other tutorials for that.
If this reduces the usage of the PHP Code Widget, well, I’ll be a happier person.
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.
So in my last post about Internationalization, I covered some non-obvious things that you should consider when adding translation capabilities to your code.
Today, let’s add to that by covering some non-obvious translation functions. You’re probably not using these, since they don’t get talked about as much. But there’s probably places where you should be using them, so knowing about them is the first step. And knowing is half the battle.
Basic functions, again
Last time I talked about these functions:
__()
_e()
_x()
_ex()
_n()
Let’s cover the ones I didn’t talk about.
Escaping output
In practice, you tend to use these mostly when outputting things onto the main page or in the admin. But, one thing you also use a lot when outputting text is the standard escaping functions. These are things like esc_html(), which outputs text in a way that makes it “safe” to go onto a webpage, without being interpreted as HTML. If the text comes from user input, then this is a good idea.
Now, if you think about it, then the text you have may be translated in some other file, which you don’t control either. So escaping that text might be a good idea too. If somebody snuck bad code into a translation file, a user might get bad things displayed without being able to easily find it.
So you could write something like echo esc_html(__('text','text-domain')), but that’s a bit wordy. Let’s talk about some shortcuts.
The esc_html__() function is the equivalent of esc_html(__(...)). It does the escaped html and the double-underscore translation all in one go. Similarly, the esc_html_e() function does the same thing, but it echoes the result, just like the _e() function would. And there’s also esc_html_x(), which is the equivalent of combining esc_html() and _x().
Along with those three are the three identical equivalents for attributes: esc_attr__(), esc_attr_e(), and esc_attr_x(). As the name implies, these combine the translation functions with esc_attr(), which is the escape function specifically intended when you’re outputting text into html attributes.
Also note there’s no shortcut for the equivalent of _ex(). It’s just not used that much, or at least not enough to need something special for it. Use an echo esc_html_x() instead.
There are no shortcuts for the other escaping functions as yet, but these can save a few keystrokes and make your code that much more readable.
The Numerical No-op
So we’ve got some shortcuts for escaping with those three functions, but where’s the love for _n()?
One of the problems with _n() is that it tends to require the strings to be in the same place that the PHP variable is. For all the other functions, you could have a big file of strings in an array, and then reference those strings by name or something elsewhere because they don’t require any PHP variables. Nothing about them is computed at the time of the output.
But not so with _n(), that $number to decide which string to use means that the strings have to be right there, they can’t be translated separately and referenced.
This is where _n_noop() comes in. The _n_noop() function basically takes the singular and plural strings for something, along with the text domain, and stores them in an array so that they can be referenced later by a function named translate_nooped_plural().
Perhaps an example is in order. Let’s go back to the tacos:
$string = sprintf( _n('You have %d taco.', 'You have %d tacos.', $number, 'plugin-domain'), $number );
What if we wanted those strings somewhere else? Like in a big file with all of our strings. Here’s a way to separate the strings from the _n() call:
$taco_plural = _n_noop('You have %d taco.', 'You have %d tacos.', 'plugin-domain');
$string = sprintf( translate_nooped_plural( $taco_plural, $number) , $number );
Now, that $taco_plural can be defined anywhere. Note that it contains no references to PHP variables. It’s basically static and unchanging. This allows us to separate it, then reference it elsewhere for the actual translation. The translate_nooped_plural() function performs the same job as _n() does, choosing which string to use based on the $number of tacos. The sprintf then pushes the $number into the chosen string, replacing the %d with the number.
Thus, that lets us extract the translatable strings out and put them anywhere we choose.
Also of note: The _nx_noop() function is a cross between _n_noop() and _x(). It takes a context for the translators as the third argument, and the domain becomes the fourth argument. Useful if you need to explain to the translators the context surrounding the pluralization choice.
Numbers and Dates
The number_format_i18n() function is functionally equivalent to the PHP number_format function. It lets you format numbers with commas at the thousands mark and so forth, except that it also takes localization into account. Not everybody uses commas for thousands and periods for decimals. This function will do the translation appropriately for that aspect.
The date_i18n() function is functionally equivalent to the PHP date function. It will handle all the same string formatting parameters as date() will, but it will cause output to be translated for month names, day-of-week names, and so forth. Of note is that it doesn’t change the format requested. If some places put days before months, for example, it won’t handle that. But it will output the month name in the native language (if the translation pack has the right month name in it). So you may want to run the date formatting string through __() as well, to let translators adjust the date format accordingly.
Wrap up
And that’s pretty much all the rest of the translation functions that I didn’t cover before. I may have forgotten a few useful ones here or there. Feel free to comment about anything I missed, or what you see most often, especially if you’re doing translations yourself.
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.
Fun fact of the day: about 37% of WordPress downloads are for non-English, localized versions.
So as a plugin or theme author, you should be thinking of localization and internationalization (L10N and I18N) as pretty much a fact of life by this point.
Fun total guess of the day: based on my experience in browsing through the thing, roughly, ohh… all plugins and themes in the directory are doing-it-wrong in some manner.
Yes friends, even my code is guilty of this to some degree.
It’s understandable. When you’re writing the thing, generally you’re working on the functionality, not form. So you put strings in and figure “hey, no biggie, I can come back and add in the I18N stuff later.” Sometimes you even come back and do that later.
And you know what? You probably still get it wrong. I did. I still often do.
The reason you are getting it wrong is because doing I18N right is non-obvious. There’s tricks there, and rules that apply outside of the normal PHP ways of doing things.
So here’s the unbreakable laws of I18N, as pertaining to WordPress plugins and themes.
Note: This is not a tutorial, as such. You are expected to already be translating your code in some way, and to have a basic grasp on it. What I’m going to show you is stuff you are probably already doing, but which is wrong. With any luck, you will have much slapping-of-the-head during this read, since I’m hoping to give you that same insight I had, when I finally “got it”.
Also note: These are laws, folks. Not suggestions. Thou shalt not break them. They are not up for debate. What I’m going to present to you here today is provably correct. Sorry, I like a good argument as much as the next guy, but arguing against these just makes you wrong.
Basic I18N functions
First, lets quickly cover the two top translation functions. There’s more later, and the laws apply to them too, but these are the ones everybody should know and make the easiest examples.
The base translation function is __(). That’s the double-underscore function. It takes a string and translates it, according to the localization settings, then returns the string.
Then there’s the shortcut function of _e(). It does the same, but it echoes the result instead.
There’s several functions based around these, such as esc_attr_e() for example. These functions all behave identically to their counterparts put together. The esc_attr_e() function first runs the string through __(), then it does esc_attr() on it, then it echo’s it. These are named in a specific way so as to work with existing translation tools. All the following laws apply to them in the exact same way.
So, right down to it then.
Law the First: Thou shalt not use PHP variables of any kind inside a translation function’s strings.
This code is obviously wrong, or it should be:
$string = __($string, 'plugin-domain');
The reason you never do this is because translation relies on looking up strings in a table and then translating them. However, that list of strings to be translated is built by an automated process. Some code scans your PHP code, without executing it, and pulls out all the __()’s it finds, then builds the list of strings to be translated. That scanning code cannot possibly know what is inside $string.
However, sometimes it’s more subtle than that. For example, this is also wrong:
$string = __("You have $number tacos", 'plugin-domain');
The translated string here will be something like ‘You have 12 tacos’, but the scanning code can’t know what $number is in advance, nor is it feasible to expect your translators to translate all cases of what $number could be anyway.
Basically, double quoted strings in translation functions are always suspect, and probably wrong. But that rule can’t be hard and fast, because using string operations like ‘You have ‘.$number.’ tacos’ is equally wrong, for the exact same reason.
Here’s a couple of wrongs that people like to argue with:
$string = __('You have 12 tacos', $plugin_domain);
$string = __('You have 12 tacos', PLUGIN_DOMAIN);
These are both cases of the same thing. Basically, you decided that repetition is bad, so you define the plugin domain somewhere central, then reference it everywhere.
Mark Jaquith went into some detail on why this is wrong on his blog, so I will refer you to that, but I’ll also espouse a general principle here.
I said this above, and I’m going to repeat it: “that list of strings to be translated is built by an automated process“. When I’m making some code to read your code and parse it, I’m not running your code. I’m parsing it. And while the general simplistic case of building a list of strings does not require me to know your plugin’s text domain, a more complicated case might. There are legitimate reasons that we want your domain to be plain text and not some kind of variable.
For starters, what if we did something like make a system where you could translate your strings right on the wordpress.org website? Or build a system where you could enlist volunteer translators to translate your strings for you? Or made a system where people could easily download localized versions of your plugin, with the relevant translations already included?
These are but a few ideas, but for all of them, that text domain must be a plain string. Not a variable. Not a define.
Bottom line: Inside all translation functions, no PHP variables are allowed in the strings, for any reason, ever. Plain single-quoted strings only.
Law the Second: Thou shalt always translate phrases and not words.
One way people often try to get around not using variables is like the following:
English is a language of words. Other languages are not as flexible. In some other languages, the subject comes first. Your method doesn’t work here, unless the localizer makes “tacos” into “you have” and vice-versa.
This is the correct way:
$string = sprintf( __('You have %d tacos', 'plugin-domain'), $number );
The localizer doing your translation can then write the equivalent in his language, leaving the %d in the right place. Note that in this case, the %d is not a PHP variable, it’s a placeholder for the number.
In fact, this is a good place to introduce a new function to deal with pluralization. Nobody has “1 tacos”. So we can write this:
$string = sprintf( _n('You have %d taco.', 'You have %d tacos.', $number, 'plugin-domain'), $number );
The _n function is a translation function that picks the first string if the $number (third parameter to _n) is one, or the second one if it’s more than one. We still have to use the sprintf to replace the placeholder with the actual number, but now the pluralization can be translated separately, and as part of the whole phrase. Note that the last argument to _n is still the plugin text domain to be used.
Note that some languages have more than just a singular and a plural form. You may need special handling sometimes, but this will get you there most of the time. Polish in particular has pluralization rules that have different words for 1, for numbers ending in 2, 3, and 4, and for numbers ending in 5-1 (except 1 itself). That’s okay, _n can handle these special cases with special pluralization handling in the translator files, and you generally don’t need to worry about it as long as you specify the plural form in a sane way, using the whole phrase.
You might also note that _n() is the one and only translation function that can have a PHP variable in it. This is because that third variable is always going to be a number, not a string. Therefore no automated process that builds strings from scanning code will care about what it is. You do need to take care than the $number in _n is always a number though. It will not be using that $number to insert into the string, it will be selecting which string to use based on its value.
Now, using placeholders can be complex, since sometimes things will have to be reversed. Take this example:
$string = sprintf( __('You have %d tacos and %d burritos', 'plugin-domain'), $taco_count, $burrito_count );
What if a language has some strange condition where they would never put tacos before burritos? It just wouldn’t be done. The translator would have to rewrite this to have the burrito count first. But he can’t, the placeholders are such that the $taco_count is expected to be first in the sprintf. The solution:
$string = sprintf( __('You have %1$d tacos and %2$d burritos', 'plugin-domain'), $taco_count, $burrito_count );
The %1$d and such is an alternate form that PHP allows called “argument swapping“. In this case, the translator could write it correctly, but put the burritos before the tacos by simply putting %2$d before %1$d in the string.
Note that when you use argument swapping, that single-quoted string thing becomes very important. If you have “%1$s” in double quotes, then PHP will see that $s and try to put your $s variable in there. In at least one case, this has caused an accidental Cross-Site-Scripting security issue.
So repeat after me: “I will always only use single-quoted strings in I18N functions.” There. Now you’re safe again. This probably should be a law, but since it’s safe to use double-quoted strings as long as you don’t use PHP variables (thus breaking the first law), I’ll just leave you to think about it instead. ๐
Law the Third: Thou shalt disambiguate when needed.
When I say “comment” to you, am I talking about a comment on my site, or am I asking you to make a comment? How about “test”? Or even “buffalo”?
English has words and phrases that can have different meanings depending on context. In other languages, these same concepts can be different words or phrases entirely. To help translators out, use the _x() function for them.
The _x() function is similar to the __() function, but it has a comment section where the context can be specified.
$string = _x( 'Buffalo', 'an animal', 'plugin-domain' );
$string = _x( 'Buffalo', 'a city in New York', 'plugin-domain' );
$string = _x( 'Buffalo', 'a verb meaning to confuse somebody', 'plugin-domain' );
Though these strings are identical, the translators will get separated strings, along with the explanation of what they are, and they can translate them accordingly.
And just like __() has _e() for immediate echoing, _x() has _ex() for the same thing. Use as needed.
Finally, this last one isn’t a law so much as something that annoys me. You’re free to argue about it if you like. ๐
Annoyance the First: Thou shalt not put unnecessary HTML markup into the translated string.
$string = sprintf( __('<h3>You have %d tacos</h3>', 'plugin-domain'), $number );
Why would you give the power to the translator to insert markup changes to your code? Markup should be eliminated from your translated strings wherever possible. Put it outside your strings instead.
$string = '<h3>'.sprintf( __('You have %d tacos', 'plugin-domain'), $number ).'</h3>';
Note that sometimes though, it’s perfectly acceptable. If you’re adding emphasis to a specific word, then that emphasis might be different in other languages. This is pretty rare though, and sometimes you can pull it out entirely. If I wanted a bold number of tacos, I’d use this:
$string = sprintf( __('You have %s tacos', 'plugin-domain'), '<strong>'.$number.'</strong>' );
Or more preferably, the _n version of same that I discussed above.
Conclusion
Like I said at the beginning, we’ve all done these. I’ve broken all these laws of I18N in the past (I know some of my plugins still do), only to figure out that I was doing-it-wrong. Hopefully, you’ve spotted something here you’ve done (or are currently doing) and have realized from reading this exactly why your code is broken. The state of I18N in plugins and themes is pretty low, and that’s something I’d really like to get fixed in the long run. With any luck, this article will help. ๐
Wrote this quick WordPress code snippet at WordCamp Louisville. It makes a /random/ URL on your site which redirects to a random post. Thought some people might find it useful.
Not a perfect little snippet, but gets the job done. Note the use of the little-used 307 redirect for temporary redirection. This is to make browsers not cache the results of the redirect, like some of them might do with a 302.
add_action('init','random_add_rewrite');
function random_add_rewrite() {
global $wp;
$wp->add_query_var('random');
add_rewrite_rule('random/?$', 'index.php?random=1', 'top');
}
add_action('template_redirect','random_template');
function random_template() {
if (get_query_var('random') == 1) {
$posts = get_posts('post_type=post&orderby=rand&numberposts=1');
foreach($posts as $post) {
$link = get_permalink($post);
}
wp_redirect($link,307);
exit;
}
}
There’s plugins that do this sort of thing too, but this is such a simple little thing that it doesn’t really need a big amount of code to do.
Edit: Added get_permalink() optimization from @Raherian.
If you read “how-to” stuff for WordPress sites around the web, then you frequently run across what many people like to call “snippets”. Short bits of code or functions to do various things.ย I myself post snippets frequently, usually made up on the fly to solve somebody’s specific problem.
One question I get a fair amount is “where do I add this code?”
The usual answer to this for a lot of people is “in the theme’s functions.php file”. This is a quick solution, but it is often a problematic one.
The reason this has become the more or less go-to place to add these snippets is because it’s complicated to explain to a newbie how to make a plugin and activate it, or to point out the problems with modifying core code, or plugin code. Saying to look for a specific file in their theme, on the other hand, is quick and easy, and until recently theme upgrades have been fairly rare.
However, as themes get upgrades, it becomes more and more incorrect to tell people to modify them directly. And telling people how to create child themes is complex, even if it’s easy to do.
So I’d like to start a new trend, and recommend that people start making Site-Specific Plugins. Most people who run WP sites on a serious level do this in some way already, but if you make it sorta-standard practice, then it’ll make things simpler all around.
How to create a Site-Specific Plugin
1. Create a new directory in the plugins directory. Name it after the site in some fashion. For example, /wp-content/plugins/example.com or something like that.
2. Create a new php file in that directory. Name is dealer’s choice.
3. Put this in the file:
<?php
/*
Plugin Name: Site Plugin for example.com
Description: Site specific code changes for example.com
*/
4. Finally, go activate your new blank plugin on the site.
Now you have a simple and specific place to add snippets. It will survive upgrades of any sort, and you can edit it to add new code on an as needed basis. What’s more, it’s kinda sorta break-proof. If the user uses the built-in plugin editor to edit it, and they add code that breaks the site, then the editor detects that on saving the code and deactivates the plugin, preventing the “white screen of death” for their site.
This is a much better way to use “snippets” than the theme’s functions.php file, and we should really use it more often in our replies to users.
WordPress plugin and theme authors could get something interesting in WordPress 3.3: a somewhat more comprehensive help screen system.
This is actually just a small part of a more long term makeover involving unifying the admin screen code base, but it’s pretty cool nevertheless. Backward compatibility is sorta fuzzy on parts of it at the moment, but not a lot of authors used these functions previously anyway, from what I can tell.
Anyway, I spent an entertaining half hour reworking the help dropdown for my SFC plugin. Here’s what it looks like in 3.3-aortic-dissectionย right now (note that the look and feel of this will probably change before final):
SFC Help screen in WordPress 3.3
As you can see, the dropdown Help menu moved into the Admin bar (along with lots of other stuff), and has some tabs on the left hand side where you can make different topics and such for different parts of the plugin.
The code for this is actually fairly straightforward, albeit in a sideways sort of way…
First we have to look at the code that adds my options page in the first place. This would work with any of the add_*_page functions, so add_theme_page and such works fine too.
This makes an options page, and then uses the assigned identifier for that page to hook the load-* action. This means that when our page is loaded, the sfc_plugin_help function will get called.
function sfc_plugin_help() {
global $sfc_options_page;
$screen = get_current_screen();
if ($screen->id != $sfc_options_page)
return;
Here, we call get_current_screen() to get the current WP_Screen object. The WP_Screen object is new to 3.3, but essentially it encapsulates an admin screen. It’s still under active development, but in the long run, it may make the task of creating admin screens much, much easier.
Anyway, right away, I do one thing and that is to check if the ID of the current screen matches the ID I was given for my options page. If it doesn’t match, then the user isn’t on my screen, and so I return having done nothing at all. This is a sort of belt and suspenders approach, since we shouldn’t be here if load-$sfc_options_page didn’t get called, but it never hurts to be sure.
The next bit is where I add my help screens. Here’s an incomplete sample of that code:
$screen->add_help_tab( array(
'id' => 'sfc-base',
'title' => __('Connecting to Facebook', 'sfc'),
'content' => "HTML for help content",
));
$screen->add_help_tab( array(
'id' => 'sfc-modules',
'title' => __('SFC Modules', 'sfc'),
'content' => "HTML for help content",
));
$screen->add_help_tab( array(
'id' => 'sfc-login',
'title' => __('Login and Register', 'sfc'),
'content' => "HTML for help content",
));
I removed the content for each one to make it clearer. Essentially, I’m just calling the object’s add_help_tab function to add my new tabs to the help screen, one by one. Simple, right?
There’s other useful bits in WP_Screen too, such as adding screen options, adding a right hand side sidebar to the help dropdown, and so forth. I haven’t figured out a use for them yet, but they’re still nice to see.
If you have a complex plugin or theme, might be worth looking into this now. Might reduce your need for end-user support. Maybe. Hard to say. People rarely look at the documentation, but inline help might be worth a shot.
My post about how to customize WordPress images with tricks like greyscale and such got me lots of feedback, so I figured I might as well turn it into a plugin.
The ImageFX plugin allows you to customize the image sizes from WordPress or custom ones for your theme, by applying filters to them.
The way it works is basically identical to my original post on the topic, only it allows the filters to be defined on a per-image-size level. It also allows the addition of a “slug” to be appended to the image filename, which is useful for cases where you want to have two images at the same size, but with different filters.
Since it was easy to do, I went ahead and created several other simple image filters that you can use for your images:
Greyscale (black and white)
Sepia tone (old-timey!)
Colorize with red, yellow, green, blue, or purple
Photonegative
Emboss
Brighten
Greyscale except red, green, or blue (classy!)
Here’s some examples. This a pic of me, Nacin, Rose, and Matt at WordCamp San Francisco. I ran it through the sepia, blue colorize, and grey-except-red filters.
These are some of the default filters included, but since I could, I went ahead and made it easily expandable too. All you have to do to define a filter is to create a function to do the image filtering you want, then call the imagefx_register_filter() function to add it.
To implement your own custom filter, you can do it like this:
imagefx_register_filter('custom-name','my_custom_filter');
function my_custom_filter(&$image) {
// modify the $image here as you see fit
}
Note that the $image is passed by reference, so you don’t have to return it. This is because the $image resource takes up a lot of memory, so to save on memory usage, you are manipulating it in place, sort of thing.
You can use any of the image functions in PHP to change the image however you like. The filters I’ve implemented are mostly pretty simple. You can see them all in the filters.php file, in the plugin.
Caveats: The plugin will only filter JPG images, to avoid the overhead of recompressing PNGs and to avoid breaking animated GIF files. Also note that I haven’t tested these filters extensively. They’re only a starting point, sort of thing. I spent all of about 20 minutes writing them, so don’t expect miracles. ๐