How To Remove (Or Change) “Private” Or “Protected” From WordPress Post Titles

If you make a post private in WordPress, the post’s title with be prefixed with “Private”. The same will happen if you password protect the post, although it will be prefixed with “Protected”. If you’d like to remove these, just add the following code to your theme’s functions.php file:

add_filter( 'private_title_format', 'yourprefix_private_title_format' );
add_filter( 'protected_title_format', 'yourprefix_private_title_format' );

function yourprefix_private_title_format( $format ) {
	return '%s';
}

The above code will remove the prefix by changing the format from Private: %s and Protected: %s to just %s where %s is the existing post title.

If you’d like to change it to something else, you can just change what the function in my example returns. If you want to change them independently of each other, then you’ll need to use two separate callback functions.

How To Create Custom WordPress Cron Intervals

This is mostly a reminder for myself so I can stop tracking it down every time I forget, but here’s how to have WordPress code execute on a different schedule than the default intervals of hourly, twicedaily, and daily. This specific example is for weekly execution.

<?php

// Add a new interval of a week
// See http://codex.wordpress.org/Plugin_API/Filter_Reference/cron_schedules
add_filter( 'cron_schedules', 'myprefix_add_weekly_cron_schedule' );
function myprefix_add_weekly_cron_schedule( $schedules ) {
	$schedules['weekly'] = array(
		'interval' => 604800, // 1 week in seconds
		'display'  => __( 'Once Weekly' ),
	);

	return $schedules;
}

// Schedule an action if it's not already scheduled
if ( ! wp_next_scheduled( 'myprefix_my_cron_action' ) ) {
	wp_schedule_event( time(), 'weekly', 'myprefix_my_cron_action' );
}

// Hook into that action that'll fire weekly
add_action( 'myprefix_my_cron_action', 'myprefix_function_to_run' );
function myprefix_function_to_run() {
	// Add some code here
}

?>

On a side note, I believe this must go in a plugin and not your theme’s functions.php which I hear loads too late.

Help Me Name My Latest Plugin

I’m having trouble coming up with a good name for my latest WordPress plugin so I thought I’d crowd source it. 🙂

My other WordPress-powered site, FinalGear.com, receives very large traffic spikes. I used to just run WP Super Cache to prevent the site from going down but Apache would still actually die under the load even though it was just serving static content. Since the site has no comments or other often changing content, the easiest solution at the time was just to throw a reverse proxy called Varnish in front it with a decent cache time (5-10 minutes per page). I’ve since switched from Apache to nginx which solves that issue but it’s still easiest to just leave Varnish there.

Varnish is set up to ignore cookies on the front end of the site. That means I get served the exact same version of the site that you (a guest) sees — no admin bar, no post edit links, and so forth. Getting to the admin area is easy thanks to an absolutely positioned hidden link in the bottom left of the site (hover over it, you’ll find it) so lack of an admin bar is no problem for me.

What is a problem though is the lack of easy way to edit a post. I currently have to go into the admin area and then browse to the post in order to edit it. So I wrote a plugin that outputs the edit post link even for people who aren’t logged in. However the link is hidden using CSS and then re-shown using Javascript only if you have a logged in cookie.

It works perfect but what to call it? My working title was “Javascript Edit Links” but that seems so bland and locks me a bit into a corner. What if I someday want to add other features to the plugin, such as even showing the full admin bar? Do you have any better ideas?

Translating Strings In WordPress Containing Multiple Placeholders

I really often see a common mistake made when translating strings in WordPress so I thought I’d write a blog post in order to shed more light on the issue.

But first, here’s a quick refresher on how to internationalize code in WordPress:

<?php _e( 'Welcome to my blog!', 'my-plugin-text-domain' ); ?>

For dynamic strings, it’d be something like this:

<?php printf(
	__( 'Welcome to my blog, %s!', 'my-plugin-text-domain' ),
	$name
); ?>

But what about when you have multiple variables to use in your string? A common mistake is to do something like this:

<?php printf(
	__( 'Welcome to my blog, %s! Today\'s date is %s.', 'my-plugin-text-domain' ),
	$name,
	$date
); ?>

The issue with this is that you’re requiring the person’s name to always come before the date. If for internationalization reasons it needs to be in a different order, then it won’t work. You’ll end up with something like Today's date is Alex. Welcome to my blog, November 2nd!.

The solution is to use standard sprintf() argument swapping parameters:

<?php printf(
	__( 'Welcome to my blog, %1$s! Today\'s date is %2$s.', 'my-plugin-text-domain' ),
	$name,
	$date
); ?>

Now translators are free to re-order the string to whatever makes the most sense for the language in question without having to worry the order of the variables.

For a more in-depth review of this, check out the WordPress Codex where many real world examples can be found.

Code Snippet: Helper Class To Add Custom Taxonomy To Post Permalinks

Say you have a custom taxonomy called “sport” and you wanted to inject “football” into the permalink of posts that have the “football” term assigned to it. How would you go about doing that? Well below is a helper class that will make it easy to accomplish exactly that.

Click here to read the rest of the post and see the code »

Code Snippet: Add A Link To Latest Post To WordPress Nav Menu

Someone on #wordpress IRC support channel was trying to add link to their latest blog post to their WordPress navigation menu, so I threw together a few lines of code to help them accomplish this.

// Front end only, don't hack on the settings page
if ( ! is_admin() ) {
	// Hook in early to modify the menu
	// This is before the CSS "selected" classes are calculated
	add_filter( 'wp_get_nav_menu_items', 'replace_placeholder_nav_menu_item_with_latest_post', 10, 3 );
}

// Replaces a custom URL placeholder with the URL to the latest post
function replace_placeholder_nav_menu_item_with_latest_post( $items, $menu, $args ) {

	// Loop through the menu items looking for placeholder(s)
	foreach ( $items as $item ) {

		// Is this the placeholder we're looking for?
		if ( '#latestpost' != $item->url )
			continue;

		// Get the latest post
		$latestpost = get_posts( array(
			'numberposts' => 1,
		) );

		if ( empty( $latestpost ) )
			continue;

		// Replace the placeholder with the real URL
		$item->url = get_permalink( $latestpost[0]->ID );
	}

	// Return the modified (or maybe unmodified) menu items array
	return $items;
}

Place the above code in a plugin or just in your theme’s functions.php file.

Create a new “Custom Link” menu item where the URL is #latestpost (which will act as a placeholder and target for the code). You can title the item whatever you please. This code will then find that menu item (by looking for the placeholder URL) and then replace it’s URL with that of the latest post’s URL. Since the filter is before the code that adds the selected CSS classes runs, the menu highlighting will even work. When you visit the latest post on your blog, this menu item will light up.

Rather simple and elegant. You gotta love WordPress hooks.

Translating WordPress Plugin Details

Plugin authors: did you know that you can allow translators to localize the plugin details that show up in the plugins list in the WordPress administration area? Your plugin’s name, description, and so forth? Well you can! It’s actually really simple to do and all you need to do is add one or two additional plugin headers to your file.

The first is Text Domain and this is the text domain for your plugin, i.e. the first argument that you are passing to load_plugin_textdomain().

The second one is Domain Path and is optional. It’s only needed if you store your translation files in a subfolder inside of your plugin’s folder.

Here’s an example load_plugin_textdomain() call from one of my newest plugins:

load_plugin_textdomain(
	'add-descendants-as-submenu-items',
	false,
	dirname( plugin_basename( __FILE__ ) ) . '/localization/'
);

That loads translation files from a subfolder called “localization” inside of my plugin’s folder. This turns into the following plugin header:

Plugin Name:   Add Descendants As Submenu Items
Plugin URI:    http://www.viper007bond.com/wordpress-plugins/add-descendants-as-submenu-items/
Description:   Automatically all of a nav menu item's descendants as submenu items. Designed for pages but will work with any hierarchical post type or taxonomy.
Version:       1.1.0
Author:        Alex Mills (Viper007Bond)
Author URI:    http://www.viper007bond.com/

Text Domain:   add-descendants-as-submenu-items
Domain Path:   /localization/

An extra line break isn’t needed nor is the extra spacing but I added both just for aesthetic reasons.

And that’s it! WordPress will then attempt to translate the plugin’s name, URI, description, author, author URI, and version fields. I personally only include the plugin’s name and description in my translation template files though as I don’t feel translators need to localize the other fields.

If you need help generating a translation template file for your plugin, log into WordPress.org and then visit the “Admin” tab on your plugin’s page on WordPress.org. You can generate a POT file for your plugin there.

New Plugin: Add Descendants As Submenu Items

When I created the navigation menu at the top of my site using the menu feature in WordPress (Appearance → Menus), I didn’t want to have to maintain anything but the top-level menu items. When I released a new plugin and created a page for it, I didn’t want to have to go into my menu UI and add it there too. So instead I wrote this plugin.

Add Descendants As Submenu Items adds a checkbox to each menu item that is of a hierarchical post type (i.e. pages). Checking this box will automatically display all descendants as submenu items on the front end of your site. You can see it in action at the top of my site — I only configured the top level menu items and everything that shows up when you hover over them has been added by my plugin rather than manually by me.

For more details and to download the plugin, check out the plugin’s homepage.