WordPress E-mails in HTML

WordPress sends e-mails in plain/text by default, and you can change that using the wp_mail_content_type filter. However, if you change the content type to text/html for all your e-mails, you might break some messages that contain links, because WordPress puts <angle brackets> around links.

From the RFC2396:

Using <> angle brackets around each URI is especially recommended as a delimiting style for URI that contain whitespace.

If you’re going to change the content type for all your e-mails issued by WordPress, don’t forget to rewrite the default messages with proper markup. You can do that with various other filters, like retrieve_password_message.

Finally, if you’re going to send e-mails in HTML, please make sure they all respond well to narrow screens on mobile devices, and preferably contain a plain/text version of the same message.

WordPress Actions vs. Filters

If you’re still wondering about the difference between WordPress actions and WordPress filters, Michael Fields posted a very cool explanation in this forum thread called Actions vs. Filters. I think it’s the best explanation of actions and filters I have seen so far, well done Michael, and keep up the good work!

Let’s pretend that WordPress is a Mexican restaurant and we have ordered a taco as illustrated by the following code…

<?php $taco = 'chicken'; ?>

Hat tip to Philip for finding this little two-year old treasure in the forums. If you’re interested in a very detailed article about the internals of actions and filters, check out Gennady’s post called Inside WordPress Actions and Filters.

Has anyone else stumbled across interesting ways of describing WordPress functions and APIs? Feel free to share your links!

Don’t Be Shy to Use sprintf with WordPress

Don’t be shy to use the printf and sprintf functions with WordPress. It makes code much easier to read. Take a look at the following examples.

echo '<a href="' . get_permalink() . '" class="link">' . get_the_title() . '</a>';

It looks quite dirty and it’s very easy to miss a quote or double-quote. Here’s one that looks a lot cleaner and easier to read:

printf( '<a href="%s" class="link">%s</a>', get_permalink(), get_the_title() );

And here’s a slightly less clean, but more secure example:

printf( '<a href="%s" class="link">%s</a>', esc_url( get_permalink() ), esc_html( get_the_title() ) );

You might think escaping the permalink and the post title is not necessary, and you’re right. However, it’s considered best practice to escape as late as possible, which is often right before the output. Here’s a more complex example, taken from the Twenty Twelve theme:

$date = sprintf( '<a href="%1$s" title="%2$s" rel="bookmark"><time class="entry-date" datetime="%3$s" pubdate>%4$s</time></a>',
    esc_url( get_permalink() ),
    esc_attr( get_the_time() ),
    esc_attr( get_the_date( 'c' ) ),
    esc_html( get_the_date() )

It also makes use of argument swapping, which is very common when working with translation functions, mainly because RTL languages would need to swap things around. It’s also very convenient to read when there are two or more placeholders.

You can learn more about sprintf (with a bunch of cool examples) in this article, and about escaping and data validation right here.

Thanks for reading and have a great day!

Github’s Asking for my Password

“Why is Github asking me to input my username and password when I try to push changes to a repository I own?” I asked this myself a couple of times before I figured out I had cloned it the wrong way:

git clone https://github.com/kovshenin/publish.git .

As opposed to:

git clone git@github.com:kovshenin/publish.git .

Where the former will use the HTTP protocol, and thus require basic authentication (username and password), and the latter will use the SSH protocol, and will try to use my SSH key instead, for password-less authentication. The former will work, but you’ll have to keep entering your username and password every time. The latter is more secure.

Simple, but tricky. No, I don’t use a GUI for version control, and neither should you, trust me :)

Quick Tip: How to Make Tweet Embeds Responsive

Twitter embeds were introduced in WordPress 3.4, allowing you to insert tweets by pasting a link to that tweet on a line of its own, in you post or page content. However, many responsive themes (including mine) resulted in broken layouts on narrow screens, since the embedded tweet will get a fixed width of 550 pixels. After a little poking around, I found an easy way to solve this with some CSS magic:

.entry-content .twitter-tweet-rendered {
    max-width: 100% !important;

Where entry-content is the class name of your content wrapper, which can be different for different themes. This will make sure that the rendered tweet block will scale along with its container. Obviously, if your existing theme is not responsive, this trick will probably not work, try Twenty Eleven ;)

You can also try stripping out the width argument by filtering on oembed_result like Otto mentioned but I think CSS is the better way to go. Tested on Android and iOS 5.

Update: Created a core ticket for Twenty Eleven and Twenty Twelve — #21680.

Tip: get_posts will suppress_filters by default

I was wondering why my posts_where filter was not being executed on my WordPress query and after a bit of poking around, I figured out that get_posts sets suppress_filters to true, unless specified otherwise, making WP_Query skip a bunch of SQL filters, including the posts_where I was trying to set. So learn the easy way — get_posts will suppress filters by default.

Hopefully this won’t be such a problem when when date_query makes it into core, since one of the most popular uses for posts_where is better date filtering.

How to Network Deactivate a WordPress Plugin

Duh! Hit “Network Deactivate” in the Network Admin, right? Yeah….

Next time, think twice before you Network Activate a WordPress plugin. It’s not too easy to deactivate it, while keeping it activated on blogs that actually use it. I wrote a little CLI script to activate a plugin of your choice on all blogs in a network:

define( 'ABSPATH', '/path/to/wordpress/' );
require( '/path/to/wp-config.php' );
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
global $wpdb;

$blogs = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs;" );
foreach ( $blogs as $id ) {
    switch_to_blog( $id );
    activate_plugin( 'your-plugin/your-plugin.php' );

printf( "Plugin has been activated on %d blogs.", count( $blogs ) );

You can use it before you network deactivate a plugin, to make sure it’s still activated on all blogs that (might) use it, but newly created ones will not have it active by default. You can then go through all the blogs with that plugin activate, and deactivate on the ones that are not using it, either manually or with a script similar to the above, depending on the plugin.

For example, you can do a check for an option that a plugin uses with get_option and if it’s empty use deactivate_plugins to deactivate it for that blog. The above trick helped me deactivate three plugins, which were barely used in a network.

What about you? How many plugins have you network activated some day, and not really using them on each and every site in the network?