Unit of Measure PHP Class

February 16, 2010

For a recent project, we developed a php class that made it easier to work with units of measure. I was surprised that there wasn’t anything like this available out there, so we decided to open source the code once it was in a good state. That day has come.

We will be updating this code (and this blog post) over the next few days and likely down the road as well. But in the meantime, here is a link to the GitHub repository: phpUOM on GitHub.

(If this goes well, we’ll hopefully be open sourcing a bit more of our code in the future.)

Hidden 404 Errors with Wordpress Plugin Pages

August 17, 2009

After a couple hours, I’ve tracked down and fixed a bug I was having with some of our Wordpress plugins. I believe that there are a few people out there having the same problem. I think there may be another solution online, but it is one of those issues that is difficult to pare down to a good search query.

Anyway here is a solution for “404 issues with plugin pages” or “lynx shows a 404, but the page still loads”, or “Google Webtools says there is a 404, but I can get to the page”, or “setting status to 200:OK still results in 404″, or “I get a 404 in IE, but refreshing the page brings it up”, or “I get random 404 errors in IE”, or “I’m getting an HTTP/1.1 404 Not Found error but the page still loads”.

You may skip ahead to the Final Solution code, but it is probably a good idea to read everything below to make sure that you are indeed having the same issue I had… and that this will actually fix your problem.

The Context

I have some Wordpress plguins (Stranger Products, Stranger Events) that generate pages outside of the core Wordpress system (i.e. they are not “wordpress pages” in the WP DB, they are web pages generated by our plugin script). To serve these pages, I add a bunch of rules to the .htaccess file to redirect stuff like /products/1/ to a product info page.

Some gallery plugins or other plugins that generate new pages may have a similar setup/issue.

The Problem

While the mod rewrite works fine, and the page loads fine, Wordpress doesn’t find a WP page or post for the query string and so sends a “HTTP/1.1 404 File Not Found” status in the header. Most web browsers will ignore this and show the content that comes after the header. It seems that IE will sometimes choke on this status, and other times show the page. Funny IE!

Google’s crawler however will not crawl that page and will let you know in a web toolkit report. Also, I noticed that the lynx command line browser for Linux would show the 404 error and then load the page.

The big issue here is that Google is not going to crawl our page.

The Fix

I spent a lot of time tracking down where in the Wordpress code the 404 status is set. Ideally, there would be a plugin “hook” near this that we could use to prevent the 404 status from reaching the browser.

The function that makes the 404 decision is handle_404(), which can be found in the /wp-includes/classes.php file. Here is the code (for Wordpress 2.8.4, similar for previous versions I looked at too):

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
function handle_404() {
	global $wp_query;
	if ( (0 == count($wp_query->posts)) && !is_404() && !is_search() && ( $this->did_permalink || (!empty($_SERVER['QUERY_STRING']) && (false === strpos($_SERVER['REQUEST_URI'], '?'))) ) ) {
		// Don't 404 for these queries if they matched an object.
		if ( ( is_tag() || is_category() || is_author() ) && $wp_query->get_queried_object() ) {
			if ( !is_404() )
				status_header( 200 );
			return;
		}
		$wp_query->set_404();
		status_header( 404 );
		nocache_headers();
	} elseif ( !is_404() ) {
		status_header( 200 );
	}
}

This would be the ideal place to say, “Hey, don’t 404 this page”, but there is no hook in here. I tried setting the $wp->did_permalink flag to FALSE, which worked sometimes, but sometimes Wordpress would write that back to TRUE after I reset it. And I’m not even sure what that flag is doing; so playing with it might cause some bugs elsewhere.

The next place to check is the status_header() function called by handle_404. This function is found in the /wp-includes/functions.php file. Here is the code:

1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
function status_header( $header ) {
	$text = get_status_header_desc( $header );
 
	if ( empty( $text ) )
		return false;
 
	$protocol = $_SERVER["SERVER_PROTOCOL"];
	if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
		$protocol = 'HTTP/1.0';
	$status_header = "$protocol $header $text";
	if ( function_exists( 'apply_filters' ) )
		$status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );
 
	return @header( $status_header, true, $header );
}

Tada! This function uses the “status_header” hook/filter before updating the header. So we can create a function in our plugin to check the status for a 404 and then return false/NULL if we know that there really is a page to load. Here’s how I did it.


The Final Solution

In PHP code for my pages, I created a global variable called $isapage and set it to true. So at the very top of any page that is giving the 404 errors, add this code:

global $isapage;
$isapage = true;

Now I add the following function and filter to my plugin code:

//this function checks if we have set the $isapage variable, and if so prevents WP from sending a 404
function ssp_status_filter($s)
{
	global $isapage;
	if($isapage && strpos($s, "404"))
		return false;	//don't send the 404
	else
		return $s;
}
add_filter('status_header', 'ssp_status_filter');

I hope this helps some people out there.

Feel free to critique this solution. Let me know if I missed something or if there are better ways to do this.

Feel free to post related issues. I may have found solutions to those along the way… or maybe a commenter can help you out.

Introducing TopWhatever

February 5, 2009

TopWhateverA new product from Stranger Studios. TopWhatever will change your life. From the about page:

TopWhatever helps you make decisions by walking you through the process of creating a “decision matrix”. Using the matrix, you can weigh your options against the criteria that are important to you.

Some decisions can get complicated quickly. The decisions you end up making can feel subjective rather than objective. TopWhatever helps you take things step by step. You end up with a decision that is sound, with the math to prove it.

The best way to understand how TopWhatever works is to view decisions that have already been made.

So check it out already. Use TopWhatever to make a decision that has been on your mind lately.

Interactive 8-Ball Facebook App

June 28, 2007

So we’ve jumped on the Facebook bandwagon a bit. You can now install the Interactive 8-Ball application to your Facebook profile.

Why would you want to install I8B on your Facebook profile?
I don’t know, but if you use Facebook as your homepage instead of iGoogle it’s nice to have I8B right there. We also update your profile and mini feed every time you ask a question through Facebook. Although this last bit can get tricky; we had a lady email us to take down a question she asked about a love prospect for fear of being had. (Which only gave us another idea for a Facebook app that we might share at some point.)

And What Happened?
I8B got a ton of traffic. In three days, we got 400 people to install the new application. Traffic to I8B trippled to 800 visits a day and then… leveled out. We actually lost 5-10 users today as people have started to uninstall the application. So growth is not exactly parabolic so far.

I guess we need something more to help the spread. (This blog post? A mention at TechCrunch? Maybe I’ll resubmit I8B to Emily Chang’s eHub.) It would be nice to have the 20,000 users that the other lame-o eight ball application on there has. Of course they got there first and so are high in the app directory and have the catchy URL at apps.facebook.com/eightball. (ours is apps.facebook.com/bettereightball) ;)

What’s next?
A WineLog app for Facebook, duh. The I8B stuff was kind of a primer for work on a WineLog application. And good thing too. It is nice to work out all of the kinks using a brand that we aren’t as invested in. This article helped me a bunch, but it also took a lot of hacking around to figure out what he meant by everything. The toughest part was fixing Facebook’s broken PHP4 client. Don’t even try messing with that unofficial one. If anyone needs help, shoot me an email or IM.

Anyway, a WineLog app would be fun. Again, I would rather just go to WineLog to see what my friends are drinking. But if you spend your day at Facebook, it’s sweet to get notifications on what people are logging. And it will hopefully introduce WineLog to some new folks. Cross your fingers.

UPDATE: Here are links to my versions of the facebook api scripts. Download them and rename them to .php. I hope to comment up the code when I get a chance, so you can see what I changed. But in the meantime, this might be a better starting place for you than Facebook’s version.

facebook.php
facebookapi_php4_restlib.php
IsterXmlSimpleXMLImpl.php

Download all of the above files, rename them to .php, and follow the tutorial instructions here (or do whatever you’re doing). The strange one at the bottom is a library to handle XML objects (PHP5 does this natively I suppose). Read here for more on simplexml44. Or here is the entire simplexml gzip file as I unzipped and installed it on my server.

Easier Way to Implement Diggstyle

April 27, 2007

Way back, I wrote the tutorial on how to create a pagination scheme similar to the one that Digg uses. The code in the tutorial was meant to educate readers on how the algorithm works.

Meanwhile, I was using completely different code for my own projects. Typically I put all of the pagination code into a function (or PHP class), which makes it much easier to use in practice. Now I’ve made available a version of this function, which people should look to first if they want a quick implementation.

  • Download the PHP code for the function here: diggstyle_function.txt.
  • To use it make a function call like getPaginationString($page, $totalitems, $limit, $adjacents, $targetpage, $pagestring);.
  • $page is the current page number
  • $totalitems is the total number of items in the set. You usually get this from a SQL query.
  • $adjacents is the number of page links to put adjacent to the current page.
  • $targetpage is the URL you want to point to. e.g. index.php
  • $pagetext is the string used to append the page variable to the URL. e.g. ?page= or &p=
  • Use this style sheet.

Read the tutorial for more help and to see an example. For a real-live example, check out my Wine Log.

Also, Mis Algoritmos is at it again with a digg-style pagination plugin for Wordpress based on this code.

Pagination Update

December 29, 2006

Earlier in the year, I wrote a tutorial on how to create pagination similar to Digg’s. The article focused on the basic algorithm for displaying the pagination, and there was definitely some opportunity for improvement in its implementation.

Well, the improvements are in. We have a modularized PHP version and a Perl version. See the updated pagination demo page for details.

Paginate Your Site Like Digg

July 7, 2006

Some people were interested in seeing the code I used to create the pagination for WineLog, which was based on the style of pagination used on sites like Digg and Flickr. I’ve put together a little demo which should help out anyone who is trying to create the same effect on their site.

Screenshot of Digg-Style Pagination in Action

(digg-style pagination demo)