firsttube.com Upgraded To WordPress 2.7

So far, one problem, two gripes.  My problem is that I can’t seem to get posts with dots in the slug title to work right, even though I once solved this problem before.  What’s worse is that it won’t fetch those posts anymore, which really sucks.

Onto my gripes. I can’t get inline replying/threading to work.  There is very little documentation on it so far. The functions are called comment_reply_link() and get_comment_reply_link(), and there’s nothing anywhere in the codex that helps, there’s little on the internet, the only place to get any real detail is the code itself, which explains:

from wp-includes/comment-template.php starting at line 949 on WP 2.7.0

 * Retrieve HTML content for reply to comment link.
 *
 * The default arguments that can be override are 'add_below', 'respond_id',
 * 'reply_text', 'login_text', and 'depth'. The 'login_text' argument will be
 * used, if the user must log in or register first before posting a comment. The
 * 'reply_text' will be used, if they can post a reply. The 'add_below' and
 * 'respond_id' arguments are for the JavaScript moveAddCommentForm() function
 * parameters.
 *
 * @since 2.7.0
 *
 * @param array $args Optional. Override default options.
 * @param int $comment Optional. Comment being replied to.
 * @param int $post Optional. Post that the comment is going to be displayed on.
 * @return string|bool|null Link to show comment form, if successful. False, if comments are closed.

It doesn’t matter much, because it doesn’t work, period, even though I’ve followed the instruction here to a t. So I’ll have to fix that in time.

My last gripe is with the new wp_list_comments() routine. I understand this is all new, but the idea that templating comments requires a callback function as a wrapper to all comments, pings, and trackbacks is clumsy at best. The codex on wp_list_comments() have nothing to explain it to people, so while I’ve dug in and gotten things working, it’s not for the feint of heart just yet, since you need to build a PHP function in your theme in your functions.php file (or create one if it doesn’t exist, which cannot be done via the Dashboard). I’m a little sad, since the theme system is so flexible and the new plugin system is just incredible, to see the new comment loop be so manual compared to the single file approach used so successfully in the past.

I know that Scoble says WordPress 2.7 rocks, and it does. Scoble doesn’t realize the shortcomings because he hasn’t tried to play with the new features, and fortunately, it very gracefully degrades. But it’s got some work to do to be perfect, for me at least.

Using the abbr tag

Kroc Camen, long time OSNews reader and frequent IM buddy of mine, has an interesting piece examining the use of the <abbr> HTML tag.  Kroc is one of those people who is very serious about the presentation and efficiency of his code, a trait I do not share, at least in practice, at least, to the same degree that he does, and it makes us good companions.  My focus is typically on clean, fast, scalable code that forsakes beauty in favor of performance.  My code, in the form of OSNews, has sustained a simultaneous Digging and Slashdotting, something of which I’m very proud.

But my CSS isn’t going to win any awards, my javascript could be collapsed a lot and made much more efficient, and my HTML often suffers from “div-itis” and “class-itis.” Enter Mr Camen, whose motto, “code is art,” is evident upon initial inspection.  Kroc’s code is not only well written, the source itself is actually beautiful.  We have collaborated on both CSS and PHP in the past and both are the better for it.  

That said, we have strikingly different positions about publshing on the web.  Kroc writes his website for himself, and as a result, publishes in HTML 5; his site doesn’t work in IE, his mindset being “if you choose to use a subpar browser, you will have a subpar experience. ”  Indeed, his site is a complete mess in IE 7, the fault only of IE and its abysmal CSS support, not the code itself.   I, conversely, attempt to code with a much more conservative bend, coding to the masses, at the expense of using several great tricks.   

Getting back on track, when it came to discussing the <abbr> tag, both of us found ourselves remarkably on the same page.  Although one can get into the nitty-gritty details and find the whole conversation trivial, I think there’s something to be said for using tags properly and getting your information properly parsed.  After all, screen readers exist with regularity today, XML is very popular (most commonly in the form of RSS), and search engines spider the majority of popular websites several times times a day if not every hour.   Using tags, and using them properly, should be important to content publishers and republishers.  

I also agree with Kroc’s point that it’s not your job to educate your reader like an encyclopedia.  The <abbr> tag is not so much about education as it is about properly marking up your  code.  

As the second wave of the browser war heats up – as Tracemonkey, Squirrelfish Extreme, and V8 start really setting themselves apart from IE in even larger ways, coding to standards will become even more important.  Understading lesser used tags is elemental in writing the best, most concise code and ranking well in search engines.

My First Plugin

I recognize that I’ve been a little wordy about WordPress lately – no pun intended – but I’m afraid that it’s really interesting to me, and probably will be for the next few days. So, if you’re growing weary of the WordPress related posts, I’m sorry.

Today I took my first stab at writing a WordPress plugin. Turns out, it’s really easy. I’m mean really easy. The plugin is pretty simple: it just searches through every post and turns the unlinked words firsttube.com into a hyperlink. However, it seems like it might be a useful plugin for some, even just as a text-replacement plugin. So we’ll see if I publish it. In the meantime, though, it took me about 15 minutes to write and then it was recognized by WordPress, which was very cool.

I have a few ideas for more involved plugins too that I may write, one day. But in the meantime, this one is pretty cool.

PHP Weirdness

Beware: this post is definitely not for the feint of heart. It includes a lot of code. You have been warned.

I wrote an application some time ago for my company that looks up the longitude and latitude of an address for use in our geocoding initiative. It relied on yahoo_geo(), a function written by PHP creator Rasmus Lerdorf and the Yahoo Maps API. It was largely dependent on this function:

function yahoo_geo($location) {
	$q = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=rlerdorf&amp;location='
		.rawurlencode($location);
	$tmp = '/tmp/yws_geo_'.md5($q);
	request_cache($q, $tmp, 43200);
	libxml_use_internal_errors(true);
	$xml = simplexml_load_file($tmp);
	$ret['precision'] = (string)$xml-&gt;Result['precision'];
	foreach($xml-&gt;Result-&gt;children() as $key=&gt;$val) {
		if(strlen($val)) $ret[(string)$key] = (string)$val;
	}
	return $ret;
}

This function worked for over two years for us with no problems at all. Then suddenly, in the last month, it started getting spotty. I fixed things by commenting out the caching parts of the function and forcing each execution to run again. Then I got errors about the libxml_use_internal_errors() function, so I commented that out. But today, the function just flat out failed, every single time returning the same error:

Warning: file_get_contents(http://XXXXXXXXXX/XXX) [function.file-get-contents]: failed to open stream: HTTP request failed! in /home/intranet/html/fetch.php on line X

What the heck? This code is all over the web. I’ve tried a million permutations of this function, including using fopen() and ob_get_contents(), and none have worked. And most frustratingly, I could load the URL successfully in Lynx and eLinks, so the machine could quickly and easily fetch the URL.

So I ventured into a sandbox I’ve never really played before: cURL. cURL is an interesting animal. But the interesting thing is, once I got it working, it worked faster than ever! So, without further ado, here is the new and improved yahoo_geo() function:

function yahoo_geo($location) {
	$q = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=rlerdorf&#038;location='.urlencode(trim($location));
	$ch = curl_init($q);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	ob_start();
	curl_exec($ch);
	$stream = ob_get_contents();
	ob_end_clean();
	if($stream) {
		$xml = simplexml_load_string($stream);
		$ret['precision'] = (string)$xml->Result['precision'];
		if($xml) {
			foreach($xml->Result->children() as $key=>$val) {
				if(strlen($val)) $ret[(string)$key] =  (string)$val;
			}
		}
		curl_close($ch);
		return $ret;
	} else {
		return FALSE;
	}
}

Note: If you’re reproducing these functions elsewhere, be careful – WordPress may have converted the quotes into smart quotes that will need to be fixed before this script will run properly.

OSNews vs. WordPress

I’ve spent quite a bit of time, over the last 5 or 6 days, diving into WordPress and learning what makes it tick.  Parts of WordPress are really impressive – just flat out cool. The way some of it works is fairly complex and deciphering it sometimes means reading page after page after page to understand an entire routine.  But sometimes, when you finally see, end to end, how something in WordPress works –  I mean really see individual bits of the engine – you have to admit it teaches you a little about PHP.  WordPress, underneath it all, is a pretty big beast and its strength and ubiquitous presence comes largely, I think, from the fact that it can do virtually anything.  The really sweet plugin system, the ways hooks work, “The Loop,” the dynamic options panel – it’s all very educational.  

The interesting thing here is that I’ve browsed the source of Slash, Scoop, phpNuke, and now WordPress, and all of them are definitively more complex and much heavier than the entire OSNews codebase. Now, before you jump all over me – firstly, Slash and Scoop are Perl, and I don’t really read Perl, so I can’t speak as an expert there.  Secondly, WordPress and Nuke both are very portable and dynamic, whereas OSNews has a narrow focus and, location-wise, is very static.  But that aside, OSNews has withstood simultaneous link bombs from Slashdot and Digg.  As amazing as WordPress is, it’s mostly amazing that it functions at all and loads in less than 2 minutes per page with as much going on as I can see behind the scenes.   That’s not a cut on WordPress, by the way.

In fact, if anything , what is really impressed upon me is how smooth and simple OSNews code is, if I may be so bold.  OSNews runs superfast due, in part, to lots of creative caching, some on-demand, some via cron.  But it also does so because of highly efficient queries that are measured for speed on their JOINs, meaning in some cases, it’s faster to do 20 simple queries than one complex one, or build a long and scary chain of “OR x=a OR x=b OR x=c OR x=d…”  Watching WordPress code in action is really fun for me, but watching OSNews work knowing what I now know about how much work PHP can cram into its threads is even more fun.

Hacking WordPress, Day Two

Thus far, my move to WordPress has been an adventure.  Here’s a few lessons learned.

First off, I was very excited about the features of WordPress.  I was really excited, most specifically, about the API, and about the rich text WYSIWYG of the backend.  I’ve done a lot of work on Small Axe’s backend, but it’s still nothing compared to WordPress.

When I imported my stuff, it worked well, but the “slugs” — or URL-friendly post titles — did not convert properly.  They converted as WordPress friendly, properly escaped slugs.  The problem was, my slugs needed to stay intact, because I didn’t want all old links to break.

Understanding the way WordPress functions is really tough for a WP newbie, because the code is so spread out, yet compact, voluminous, yet digestible. Start with index.php, onto wp-blog-header.php, into wp-settings.php, and then you find the massive list of files in the wp-includes directory.  You’ll dig all over trying to find files to find includes in includes in includes. I finally found a great article that tries to explain the WordPress slug architecture. It’s fairly complex. Much of it lives in/wp-includes/query.php. However, my problem was very specific.

Many of my post slugs had periods in them. The period does not interfere with the URL, but WordPress doesn’t like them, and somewhere in the massive beast. So I had to find the page that “gets” posts. Lo and behold, there is a function called “get_posts” that lives in /wp-includes/query.php. I kept poking around. Like anyone who keeps digging, eventually, you’ll find yourself in wp-includes/formatting.php. And there it is.

Slug posts get sanitized – like everything, virtually all input is strictly sanitized – by a function called sanitize_title_with_dashes(). This function generates the slug. In order to include dots in your slug titles, just replace lines 366 and 267 (on WordPress 2.6.0) with this:

$title = preg_replace('/&amp;+?;/', '', $title); // kill entities
$title = preg_replace('/[^%a-z0-9 _.-]/', '', $title);

Then your slug titles will not strip periods. Of course, I don’t recommend you actually use periods, I just wanted them to work when fetching old posts created before I knew any better.

After that adventure, I have to tell you, I’m really loving WordPress. There are some incredible plugins that have done some amazing functionality extension for me. So far, so good.

Dope Wars for the iPhone

I love my jailbroken iPhone, and I am always looking for a new “game of the week.” I’ve been through several, at first, it was LightsOff, but that ends at 225 levels or so. Then it was Five Dice. Then 4 Balls, Domino, and finally PuzzleManiak. I was so happy recently when someone decided to port Dope Wars to the iPhone in the form of “iDope.”

iDope iDope currently has a lot of bugs. Mainly, your jacket storage is irrelevant, you can actually store unlimited items, you just can’t buy unlimited items unless you hit “buy all.” You can’t store money in a bank. It never ends until you die. You are mugged or fight the cops maybe 80% of the time you travel. But most importantly, this:

Notice my dollars? That’s right, I have $2,147,483,647. Two billion, one hundred forty seven million, four hundred eighty three thousand, six hundred forty seven dollars. Recognize that number? If you read my blog regularly, you might. After all, it’s the upper limit of signed integers. The game is officially boring – no matter what I do, I’m always capped at that number, I can never get more money. I wonder if the iPhone can support BIGINT.

Anyway, I really hope to see iDope get some love and attention, because Dope Wars is a fabulous and addictive game, but as is, I eventually get to the upper limit and have to start over… and over… and over.

Integers on the Intertubes

Some time ago, I wrote an application for my company. Like most weblets I’ve written, this used PHP and either MySQL or MSSQL for the backend. This particular application logged all phone calls. As part of the record, it would record the caller’s account number, which is a 5 or 6 digit integer.

So, I got a phone call from the director of our customer contact department this week. He was concerned about the reports. He made a decision last week that when a call came in that was a lead – in other words, a non-customer, that his people would fill the phone number from the caller ID into the account number field. But when he ran his export reports, he found that hisn techs had entered this phone number for ALL of the calls: 429-496-7295. That’s weird, he said. So he called me and asked why that was. I checked all the calls and most were from one woman, so my first instinct was “Check if her browser has autocomplete turned on”. But he swore that he tried it too and gotten the same result.

I checked the database and sure enough, it was right there: 429-496-7295, in all of the fields. So I went back to the code. In short, I took the input from the form, and declared it like this:

$accountnum = (int) $_POST['accountnum'];

Pretty straightforward: explicitly declare the type. So, I started my debugging by attempting to manually enter the data into the database. Sure enough: the account key field showed this: 4294967295.

So, I went back to the PHP and started by dumping out the raw SQL query:

INSERT INTO calls ('','x','x','x','4294967295','x','x');

What? So the database automatically converts it to this weird phone number and PHP does too? Suddenly it occured to me. One of the benefits of 64-bit computing is the ability to address more memory. There are limits to what can be done in 32-bit computing, and one is that integers have a limit! In this case, a database field called “integer” is limited to numbers between -2,147,483,648 and +2,147,483,647. It just so happens that the number is the same length as a US phone number – 10 digits. Changing the db field to “BIGINT” allowed me to manually run the SQL query and it worked. But the app still didn’t.

PHP’s int() and (int) $var syntaxes both conform to the integer limit. So I devised a work around:

$ac = $_POST['accountnum'];
if(!is_numeric($ac) { $ac = (int) $ac; }

It’s not gorgeous, but it will more than suffice for an internal app. We web programmers don’t usually have to deal with big integers, so it’s totally possible that web developers would never have had occasion to handle a situation like this. Here’s looking forward to native 64-bit for our next server, though.