WordPress memcached 3.0.0

Some software is so stable that it becomes stagnant. Yesterday’s update of the WordPress object cache drop-in for memcached flings it from both categories, back into active development where it is sure to capture the attention of WordPress site administrators around the world.

So much for drama and spin. All that really happened was this: I pushed a major-version update that finally allows `wp_cache_flush()` to work for WordPress sites using memcached. You probably shouldn’t care at all; you had better click away to a video of a suburban father longboarding with a short-legged dog.

In case you do care, it can only be because you belong to the elite club of techies who administer a WordPress site with the help of memcached. Our records on this population are scarce. By one estimate–surely a miscalculation–there are fewer than ten installations of this software in the world. You may call it hubris but I suppose the number might stretch well into two-digit territory.

What you few need to know is this: upgrading to 3.0.0 will instantly flush your entire cache. This will happen because the key format has changed. I didn’t bother writing any code to gradually migrate keys, nor do I offer any other strategy mitigate this potentially catastrophic effect. You should be keen enough to handle it.

Beyond that, you can look forward to fewer problems along the lines of WordPress getting stuck in a database upgrade loop. This is when you’ve upgraded your database but WordPress keeps insisting that you haven’t, locking you out of wp-admin. That’s what happens when `wp_cache_flush()` has no effect. That’s just how it was for multisite installations because memcached’s own flushing mechanism was too blunt for such use.

How it works is not too hard to invent. Cache keys are automatically prefixed with a number that pseudo-uniquely represents the current “flush count” of either the current site or the global cache. Flushing is accomplished by incrementing that counter so that stale entries are hidden to subsequent accesses. The counters are stored in memcached so they exhibit the same performance characteristics as the cache entries they marshal.

2016 is not the first time we have tried this. Eight or so years ago, the same strategy was attempted on what was and is the world’s largest WordPress installation. Sensing trouble, we backed away from the high road and skirted the problem by inserting proprietary code in our copy of WordPress. If you’re the type that wants to dive into the gory details of these hacks, we have a special place for you.

We revisit the high road now because time has taught us to lean into trouble. We cherish our scars and we regret having sustained so few of them over the years. Second, we want future projects to hold tighter to the ethos of open source software and pushing improvements upstream for all to enjoy.

Like all versions of WordPress and this drop-in extension, 3.0.0 is free of charge. It will cost you one or two cache reads every time WordPress generates a page. If you find this expense immodest then I hope you will contact me about your use case.

I hope 3.0.0 proves stable enough to vanish back into obscurity. If it gives you trouble, come find me and we can make 3.0.1 together.

Thanks to Peter Westwood for reviewing the code and suggesting an improvement.

WCSF 2011 Voodoo

Rarst asks: what magic turns pretty permalinks into query variables?

The setup:

The magic:

foreach ( $rewrite as $match => $query ) {
	if ( preg_match("#^$match#", $request_match, $matches) ) {
		// Got a match.
		$this->matched_rule = $match;
		break;
	}
}

The real voodoo is in creating the rewrite rules. Example: bbPress

  • register_post_types
  • register_taxonomies
  • add_rewrite_tags
  • generate_rewrite_rules

Exercise: optimize parse_request by restructuring the rules into a tree.

Nacin suggests: wp-hackers Skip Main Query

  • the grand scheme of things (png, blog post)
  • $wp->init()
  • class freshlypressed_wp extends wp
  • wp() calls $wp->main()
  • $wp->main() calls $this->parse_request()
  • $this is a freshlypressed_wp

Problems:

  • Can’t extend a variable class (class my_wp extends $wp_class)
  • No pluggable inheritance chaining
  • No way for several plugins to cooperatively extend a class

Shape My WordCamp Talk

Now that Jane’s announcement has made it official, I need to prepare for my talk at WordCamp San Francisco. The working title is “Deep Voodoo: How the innermost innards of WordPress work” and the working content is nil.

This is where you come in. As a core contributor or plugin developer, you are aware of areas in WordPress code that scare you. I’ve been there and back again. I’ve digested, debugged and patched some of the most labyrinthine logic. I’ve even written some of the worst of it. On Saturday, August 13, I will try to make sense of it for everyone.

Please take a minute to recall something in the core code of WordPress that really stumps you. Ask me about it. I will try to work all of your comments into my talk, provided that I can’t answer it with a quick reply, a link to the Codex or a Google search.

If this gambit of asking for questions beforehand fails, maybe I’ll just give a tour of my personal favorite fork of WordPress in which every function block is shaped like a pony. (Please don’t let that happen.)

WordPress.com Stats 1.8: Sparkline

Just ahead of WordPress 3.1, we released WordPress.com Stats 1.8. The new Stats plugin includes some small fixes that will make it easier for us keep the plugin’s reports in sync with the reports seen on WordPress.com. The plugin’s reports are a few versions behind so look for rapid improvement in the coming weeks. But what’s most exciting about Stats 1.8 is how it works with a new feature in WordPress 3.1: the admin bar.

screen shot of admin bar
The admin bar on my self-hosted blog.

Stats 1.8 adds a tiny bar chart (called a “sparkline”) to the admin bar. To make this chart more interesting, and not just a copy of what you can already see in your stats report page, we zoomed in on the time axis. Rather than show one data point per day we show each of the last 48 hours. Following your blog’s time zone setting, lighter and darker bars represent daylight and nighttime hours.

Design credit goes to Joen and MT. The sparkline design seems simple and obvious now, but it took a lot of tries to get it that way. It wouldn’t have happened without their contributions.

Of course, we intend to bring the new sparkline to the WordPress.com admin bar as soon as possible. Remember how we said the plugin’s stats reports are a few versions behind the WordPress.com reports? With the admin bar it’s the reverse. Self-hosted bloggers are the first to get this upgrade. Everyone on WordPress.com will have it soon.

WordPress code surprise: wp_sprintf

_DSC3433
by Ulf Wendel, on Flickr

Everybody loves PHP’s sprintf(). We use it everywhere. There are just some things it doesn’t do, like format lists in sentences. Three years ago, while working on the Media Library, I needed a way to list categories or tags in a sentence. And, by golly, it would need Oxford commas and localization to be worthy of WordPress.

 

Problem solved

I wrote wp_sprintf() as a wrapper for sprintf(). It uses WordPress filters to customize the formatting directives. WordPress only uses this in one place, the function where I needed to list categories and tags: get_the_taxonomies(). This is used in standard template tags so I estimate wp_sprintf() has run at least a trillion times without fanfare. The time has come to give wp_sprintf() the attention it deserves.

wp_sprintf

The calling interface is identical to sprintf():

string wp_sprintf ( string $format [, mixed $args [, mixed $... ]] )

Internally, wp_sprintf() splits the format string into fragments that begin with a single ‘%’. It sends each fragment through the 'wp_sprintf' filter with the appropriate $args, respective of numbered directives (‘%1$s’). If the filter did not modify the fragment, it is passed through sprintf(). The processed fragments are concatenated and then returned.

Functionally, wp_sprintf() should be identical to sprintf() until a filter is added which implements a new formatting directive, or supersedes any of the standard ones. It is certainly less optimized so it should only be used when a customized directive is needed.

wp_sprintf_l

The only 'wp_sprintf' filter now in core is wp_sprintf_l(), which adds a new directive to format arrays into lists, %l:

wp_sprintf('%s: %l.', 'Tags', array('Cats', 'Dogs', 'Birds'));
=> 'Tags: Cats, Dogs, and Birds.'

Our filter, wp_sprintf_l(), receives a format fragment and the $args that corresponds with its position or number. It returns the first fragment, ‘%s: ‘, unchanged. When it sees ‘%l.’ it replaces the %l directive with a formatted list.

WordPress always tries to make text beautiful. To that end, wp_sprintf_l formats lists with Oxford commas. Two items are “cats and dogs”. Three or more items are “cats, dogs, and birds”. However, if you don’t like Oxford commas you can remove them:

function remove_oxford_commas( $separators ) {
    $separators[ 'between_last_two' ] = ' and ';
    return $separators;
}
add_filter( 'wp_sprintf_l', 'remove_oxford_commas' );

Our list formatter also respects language differences. WordPress translations include wp_sprintf_l()‘s separators so that, for example, the Spanish translation always separates the last two items with ‘ y ‘ with no comma.

You can use <code>wp_sprintf</code> with the ‘%l’ directive anywhere in WordPress since 2.5.0. It’s a lot easier than writing a <code>foreach</code> loop every time.

Something new

Recently a prominent bug crept into some code when the integer argument for %d was wrapped in a call to number_format(). Everything after the first comma was lost. I wished there were a formatting directive to mimic number_format.

While I’m thinking about it, here’s a possibility: ‘%n’. It should automatically localize the thousands separator and decimal point; this alone makes it a compelling upgrade. It should also accept at least one specifier for precision. The other specifiers (sign, padding, alignment, width) would be nice but not necessary.

Lisp alien
Image via Wikipedia

p.s. Lisp rocks!

Yesterday I finished reading Conrad Barski’s entertaining Lisp primer, Land of Lisp. He gives only a whiff of Lisp’s format function but I was blown away. It provides tabulation, justification, iteration, recursion, conversion, conditions, and never mind making a cup of coffee, it could run a chain to compete with Starbucks. Here’s a taste:

(format nil
        "~{~a~#[~;, and ~:;, ~]~}"
        (list "Cats" "Dogs" "Birds"))
"Cats, Dogs, and Birds"

Theme name idea: Severance (from the GPL)

With so much hullabaloo clogging the air, I don’t even need to introduce the topic.

I predict that somebody is going to write a theme that allows a lot of new, proprietary themes to be written without the pesky GPL contagion.

Sandbox accomplished that for people who were happy writing CSS and using their own images. They could create a non-GPL skin for Sandbox and nobody would question that. Where Sandbox falls short is in its markup which, though it was thoughtfully written, could never be all things to all people.

So, I expect somebody to write a clever WordPress theme that severs the HTML markup from the WordPress-derived PHP code, properly apply the GPL license to the PHP part, and make a bundle on proprietary skins. You can even call it Severance and I won’t ask for a dime.

(I have been an employee of Automattic since 2005. My employer had no input on this post. However, a salary alone can affect one’s outlook on economic issues.)

SxSW Interactive 2010 WordPress Bonfire

Assuming the county burn ban remains lifted, Boren and I intend to have a big ol’ Texas cedar fire in my back yard during, immediately before, or immediately after South by Southwest Interactive. A bunch of Automattic employees and WordPress contributors are expected.

If you are seriously interested in getting away from Austin (about 45 minutes) to throw small trees on a large fire, please tell me your best evening for this activity. Please also specify whether you will be able to provide responsible transportation for others.

UPDATE: Leaning toward the 16th based on a few answers. Would coinciding with the closing parties be a feature or a bug?