Second Class Citizen

Occasionally someone will pipe up and make you realise the sad truth amongst web developers, or for that matter, programmers. We are second class citizens in the eyes of many.

Gone are the days where making a computer do something different is cool, No, Now its a job, anyone can do it, you’ve just got to learn to code..  heck, some people are purely programmers for a day job, with no outside interest in it.

There Are No Famous Programmers – Zed A. Shaw (http://sheddingbikes.com/posts/1275989245.html)
Let me tell you about this cool new web server. I figured out how to merge the ZeroMQ event polling system with the libtask coroutine library so that you can use libtask to handle tons of TCP/UDP and ZeroMQ sockets in a single thread. I then took this very cool hack, and started building a web server using my Mongrel HTTP parser, but I modified the parser so that the same server on the same port can handle HTTP or Flash XMLSockets transparently. The next step is to get this server to route HTTP and XMLSocket JSON messages to arbitrary ZeroMQ backends. I was inspired by this so much that I registered utu.im and may try to bring it back. Not sure how or when though.

Sounds cool right? Totally doesn’t matter one bit. I could hack on projects like this and nobody would care at all because I’m a famous programmer, and there is no such thing as famous programmers. I don’t exist. I’m an enigma.

And he’s right, Name a “sucessful” startup who you can think of the name of the current CEO, I’m sure you can think of one, Did they write the product you’re associated with them however? In most cases, No. They’re just the ones with the vision, The one with money, The one with the guts to say “This could work!”. Being a programmer isnt enough anymore, you need a masters degree in marketing, A bucket load of cash, and a face to put forward – and face it, you’re not it.

Gone are the days when a single person can be a superstar, without the help from others, you’ll never reach gold; and if you do, be sure your programming days are long gone..

You’re doing it wrong #2

 

Welcome to part #2, If you missed #1, go check it out.

As i mentioned in the last posting, This time wp125 is featured again, No, Please dont get me wrong, i’m not just targeting certain plugins here, It’s merely the plugins which I use, which i have to modify  and/or cleanup for whatever reason, I’ve chosen WP125 to be used for this project, so here i am cleaning up some code. Also featured in the 2nd part of this posting, is TDO Mini Forms.

Who has ever seen an error message like this one?

Notice: Undefined index: wp125action in G:\www\nrtt\wp\wp-content\plugins\wp125\adminmenus.php on line 9
Notice: Undefined index: wp125action in G:\www\nrtt\wp\wp-content\plugins\wp125\adminmenus.php on line 13
Notice: Undefined index: wp125action in G:\www\nrtt\wp\wp-content\plugins\wp125\adminmenus.php on line 22
Notice: Undefined index: wp125action in G:\www\nrtt\wp\wp-content\plugins\wp125\adminmenus.php on line 26

I’m willing to bet  a lot of people would’ve seen this one time or another, It comes down to a very very VERY lazy developer in my opinion, Simply because its best programming practice to never actually hit this case..

The code which is causing this:

function wp125_write_managemenu() {
…<snip>…
//Handle deactivations
if ($_GET[‘wp125action’] == “deactivate”) {

Doesnt look too harmful really, now does it? Thats because, By itself, Its not harmful at all other than an annoying message, The harmful part, is where similar code is used, and its merely assumed that certain array items exist, The issue arises that it can make bugs slip by unnoticed..

So, Whats the correct way? Simply check that the Array item exists before comparing it against something else.

The simplest method would be:

if ( isset($_GET['wp125action']) && ($_GET['wp125action'] == "deactivate") {

Or alternatively, If you never want to fire when the array item is empty:

 if ( !empty($_GET['wp125action']) && ($_GET['wp125action'] == "deactivate") {

Now, that wasnt too hard was it? Much cleaner, reduces warnings, and potentially reduces the risk of bugs.

Once again, All changes made are available as a Diff, This diff also includes the changes made in par #1, This has been written as of version 1.3.6.

Now, Onto the second plugin, TDO Mini Forms, This isnt actually a half bad plugin overall,  However, The code can be a bit messy for lack of a better word thanks to the many many many options and defines it uses.

Most of the issues i’ve got with this plugin, boils down to mis-use of constants, for example:

Notice Use of undefined constant TDOMF_OPTION_WIDGET_MAX_HEIGHT - assumed 'TDOMF_OPTION_WIDGET_MAX_HEIGHT' in G:\www\nrtt\wp\wp-content\plugins\tdo-mini-forms\admin\tdomf-options.php on line 604

Upon actually looking through he code, The Define was used in many places, but never actually defined. However, TDOMF_OPTION_WIDGET_MAX_WIDTH, and TDOMF_OPTION_WIDGET_MAX_LENGTH were, But guess what, The latter was never actually used, other than during option creation.. It’s a simple typo really.. But a quick fix never the less.

The main thing that has been bugging me with this plugin however, are these splattered around:

Notice: Use of undefined constant REQUEST_URI - assumed 'REQUEST_URI' in G:\www\nrtt\wp\wp-content\plugins\tdo-mini-forms\admin\tdomf-form-options.php on line 15

It looks like the plugin is expecting some form of register_globals for  the $_SERVER items to be enabled, Well, Do i have news for you… Its not! To many programmers that  may have sounded like the actual problem, But the problem is actually a coding flaw.. (as expected)

if(preg_match('/tdomf_show_form_menu/',$_SERVER[REQUEST_URI])) {

May not see something wrong with that, But, You should. $_SERVER contains an array element called ‘REQUEST_URI’, which is what the author intended to access, But instead, what they have asked for, Is the $_SERVER array element whose name is within the REQUEST_URI definition.. PHP is smart enough to convert that REQUEST_URI into a string, and so the code works as expected, for now.. But it’s still sloppy, Adding 2 apostrophe’s into the mix fixes everything.. Quick and simple really..

if(preg_match(‘/tdomf_show_form_menu/’,$_SERVER[‘REQUEST_URI’])) {

And the final piece of the puzzle for this posting:

Notice: Trying to get property of non-object in G:\www\nrtt\wp\wp-content\plugins\tdo-mini-forms\admin\tdomf-edit-post-panel.php on line 36

Another common type of warning produced by PHP, Very similar to the first Array item above:

function tdomf_edit_post_panel_admin_head() {
   global $post;
   // don't show on new post/page
   if($post->ID > 0) {

Now, This wouldnt be all that bad really.. If it wasnt for this code:

add_action( 'admin_head', 'tdomf_edit_post_panel_admin_head' );

The end result, much like I explained in Post #1, Is that running code designed for a SINGLE page on EVERY page load, is not a good thing to do, eventually you’ll hit a road bump like this one..

While the most appropriate fix for this, would be to simply only hook the function to run on the post edit page, Due to this plugins insisting to be backwards compatible at one stage or another utilising the latest hook names is not always possible, So merely adding an is_object() call in there can silence and fix everything quickly:

function tdomf_edit_post_panel_admin_head() {
 global $post;
 // don't show on new post/page
 if(is_object($post) && $post->ID > 0) {

I should however note, That this plugin includes compat code for WordPress < 2.5, Whilst, It utilises WordPress 2.8 functionalities now. Plugin Authors: Keep an eye on your obsolete code, it increases complexity, and will eventually end up causing a bug. My methodology is to only support the latest WordPress release.. It’s not worth your time developing for users not upgrading their version of WordPress. Yes, You’re going to have people complain the plugin isnt compatible, but in reality, you’re doing them a favour, If they dont upgrade WordPress, they’ll have other bugs.. Your plugin not working is the least of their worries (Or should be) .

Thats it for now, TDO Mini Forms also contains many MANY uses of undefined variables, eg:

Notice: Undefined variable: edit in G:\www\nrtt\wp\wp-content\plugins\tdo-mini-forms\include\tdomf-form.php on line 387

But the plugin is too large for me to want to go in and fix everything,  what has impacted me the most has been fixed, i’ll leave it as that.

Until next time, The changes made to TDO Mini Forms is available as a Diff, as of version 0.13.5. Apologies for the Diff here,I’m having issues with Line endings, Tortoise SVN isn’t respecting its own setting – You’ll have to patch a local copy and set it to ignore line ending changes..

 

EDIT: Fixed typo’s and lack of English. Sorry, I need a new computer, this T key hardly ever works when i want it to..

You’re doing it wrong #1

Welcome to a new series of mine, You’re doing it wrong. Now, You may’ve guessed what this series is going to be about.. WordPress “Programmers” doing things wrong.

Right now, I’m writing a new theme for a website, utilising a few plugins,  one of them is WP125.

 Notice: Trying to get property of non-object in G:\www\nrtt\wp\wp-includes\general-template.php on line 366

Yep, You’re doing it wrong. First glance it looks like its caused by WordPress, but after a lot of debugging, Here’s a stacktrace:

#0 G:\www\nrtt\wp\wp-includes\general-template.php(367) stackTrace(Array ( ) )
#1 G:\www\nrtt\wp\wp-includes\script-loader.php(410) get_bloginfo(Array ( [0] => text_direction ) )
#2 unknown(unknown) wp_default_styles(Array ( [0] => CONVERTED OBJECT OF CLASS WP_Styles ) )
#3 G:\www\nrtt\wp\wp-includes\plugin.php(414) call_user_func_array(Array ( [0] => wp_default_styles [1] => Array ( [0] => CONVERTED OBJECT OF CLASS WP_Styles ) ) )
#4 G:\www\nrtt\wp\wp-includes\class.wp-styles.php(31) do_action_ref_array(Array ( [0] => wp_default_styles [1] => Array ( [0] => CONVERTED OBJECT OF CLASS WP_Styles ) ) )
#5 G:\www\nrtt\wp\wp-includes\functions.wp-styles.php(72) CONVERTED OBJECT OF CLASS WP_Styles->__construct(Array ( ) )
#6 G:\www\nrtt\wp\wp-content\plugins\wp125\adminmenus.php(8) wp_enqueue_style(Array ( [0] => thickbox ) )
#7 G:\www\nrtt\wp\wp-content\plugins\wp125\wp125.php(75) require_once(Array ( [0] => G:\www\nrtt\wp\wp-content\plugins\wp125\adminmenus.php ) )
#8 G:\www\nrtt\wp\wp-settings.php(566) include_once(Array ( [0] => G:\www\nrtt\wp\wp-content\plugins\wp125\wp125.php ) )
#9 G:\www\nrtt\wp\wp-config.php(109) require_once(Array ( [0] => G:\www\nrtt\wp\wp-settings.php ) )
#10 G:\www\nrtt\wp\wp-load.php(30) require_once(Array ( [0] => G:\www\nrtt\wp\wp-config.php ) )
#11 G:\www\nrtt\wp\wp-admin\admin.php(20) require_once(Array ( [0] => G:\www\nrtt\wp\wp-load.php ) )
#12 G:\www\nrtt\wp\wp-admin\edit.php(10) require_once(Array ( [0] => G:\www\nrtt\wp\wp-admin\admin.php ) )

Do you notice whats happening here?  A seasoned WordPress developer should.. But many will not, As it’s a huge problem amongst some plugins..

The issue at hand here, Is that the WP125 plugin, is running code as soon as its included, In this case, its registering styles and scripts as soon as the plugin is included. NOT a good thing to do.

A plugin should NEVER run any code as soon as its included*, All code should be placed inside actions.

Eg, Instead of this:

if(is_admin()){
 wp_enqueue_script('jquery');
 wp_enqueue_script('thickbox');
 wp_enqueue_style('thickbox'); 
}

It should be:

add_action('admin_head', 'wp125_enqueue_styles');
function wp125_enqueue_styles() {
 wp_enqueue_script('jquery');
 wp_enqueue_script('thickbox');
 wp_enqueue_style('thickbox'); 
}

*1: Obviously, there are some cases where running code is considered ok, but it should be avoided. I’m ignoring calls to add_action/add_filter as running code here, as thats the way things should happen.

There  is one more thing which should be noted as well.. another thing a plugin should NEVER do, Is enqueue Scripts and Styles for EVERY administration page, Only load them on the pages which require the script. So lets take that last semi-better-than-original  sniplet and convert it to something which is how ALL plugins should be registering their scripts and styles:

So, Now I’m going to introduce you to one more function which many developers seem to miss, the action admin_print_scripts-<slug>

This action is actually pretty simple, On every pageload of WordPress Administration, many dynamic hooks are fired, in particular interest today, is the admin_print_scripts-<slug> hook. This fires when WordPress decides its time to start printing the <script> and <link rel=”stylesheet” /> items into the head of the document. This is where plugins should be hooking their addition of styles and scripts, As well as printing any extra <head> content to fit into the WordPress admin pages for their plugin.

Without going into it in depth, I’m just going to give a chunk of code, The only thing worth noting, is if you’re not sure of the slug of your page, Quite handy is, that the add_menu_*() functions will return it.. So, Finally, Here we go:

//Add the Admin Menus
add_action('admin_menu', 'wp125_add_admin_menu');
function wp125_add_admin_menu() {
 load_plugin_textdomain('wp125', PLUGINDIR.'/'.dirname(plugin_basename(__FILE__)).'/translations', dirname(plugin_basename(__FILE__)).'/translations');
 $pages = array();
 $pages[] = add_menu_page(__("125x125 Ads", 'wp125'), __("Ads", 'wp125'), MANAGEMENT_PERMISSION, __FILE__, "wp125_write_managemenu");
 $pages[] = add_submenu_page(__FILE__, __("Manage 125x125 Ads", 'wp125'), __("Manage", 'wp125'), MANAGEMENT_PERMISSION, __FILE__, "wp125_write_managemenu");
 $pages[] = add_submenu_page(__FILE__, __("Add/Edit 125x125 Ads", 'wp125'), __("Add/Edit", 'wp125'), MANAGEMENT_PERMISSION, 'wp125_addedit', "wp125_write_addeditmenu");
 $pages[] = add_submenu_page(__FILE__, __("125x125 Ad Settings", 'wp125'), __("Settings", 'wp125'), MANAGEMENT_PERMISSION, 'wp125_settings', "wp125_write_settingsmenu");

 foreach ( $pages as $my_page )
   add_action('admin_print_scripts-' . $my_page, 'wp125_register_scripts_styles', 9); //Add it a little earlier.

 //Include menus
 require_once(dirname(__FILE__).'/adminmenus.php');
}

function wp125_register_scripts_styles() {
 wp_enqueue_script('jquery');
 wp_enqueue_script('thickbox');
 wp_enqueue_style('thickbox');
}

The main benefit of behaving yourself? Much less chance of screwing up another admin page’s styling or JavaScript :)

Stay tuned for the next edition of this, Where once again, WP125 will feature, along side TDO Mini Forms

See Attachment for a .diff of the changes made to the plugin. NOTE: This is as of version 1.3.6

Dear commenters: Emails do not work :)

Just a quick notice, I do not get emails for comments on this blog, Thanks to debians utterly horrible default packages and my inability to work out how to configure sendmail/postfix under debian, I hereby give up.

Every other distribution of Linux i have ever used has allways been easy to setup, and has always had sane default options for their packages, to the extent that if it uses a different username for a package, that username will be marked as trusted in every other package, debian? No.. Debian is too good for everyone else, Debian is for those people who are true linux hackers, its designed to be as impossible as it can be, yet still will have people bowing in its footsteps. Bad debian! Bad! get back in your kennel, I would be using Slackware right now if i had the choice.. Hm… I wonder how hard it would be to install slackware on this VPS…

No.. I’m not after pointers, the future of this VPS install is under question, I dont think i’m interested in spending another hour of my time battling this stupid setup.

If  for some reason, you leave a comment, and need a reply to it, please drop me a line at wordpress@dd32.id.au and i’ll see to replying to the comment and yourself, I should probably check my own blogs dashboard more often.. but its rarely a location i visit :)

The problems of get_posts() and custom post_type’s

Allright, Generally i’d not complain, I’d just make up a new Trac ticket and patch it.. But i’m seriously sick of this defect of WP_Query, A number of times i’ve just given up attempting to achieve my goal and doing it some other method which wouldnt involve hacking up everything..

The problem?

Add a new record to the WP_Posts table, with a custom post_type, now try to retrieve that post. Ah, I hear you say “Thats Easy! Just pass post_type to get_posts()” WRONG!,
Well, yes, In an ideal world, that would be the case, But no, not in this case.

First, Lets add an actual record:

[sourcecode language=”php”]
$url = ‘http://dd32.id.au/’;
$content = ‘DD32 is awesome!’;
$datas = array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘custom_status’, ‘post_title’ => $url, ‘post_name’ => $url, ‘guid’ => md5($url), ‘post_content’ => $content);
wp_insert_post($datas);
[/sourcecode]

What have i done? Just inserted a stock standard post of type ‘custom_type’ with a non-standard status. Nothing odd there.

Now, Lets retrieve that post.

First thing, Lets check that get_posts() can handle a custom post_type:

[sourcecode language=”php”]
var_dump( get_posts( array(‘post_type’ => ‘custom_type’) ) );

array
empty
[/sourcecode]

Allright, That didnt work, Better check the query used:

[sourcecode language=”sql”]SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_type = ‘custom_type’ AND (wp_posts.post_status = ‘publish’) ORDER BY wp_posts.post_date DESC LIMIT 0, 5[/sourcecode]

Ah, It doenst like our post_status, Not a probblem, Letslet it load all status types:

[sourcecode language=”php”]
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’) ) );

array
0 =>
object(stdClass)[132]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168’ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
[/sourcecode]

Looks good to me, Everything seems to have been set correctly.

However, hang on, What happens when i only want to retrieve a specific item? Well, I guess we need to specify some arguements to retrieve a single record:

[sourcecode language=”php”]
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘p’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘page_id’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘name’ => $url ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘pagename’ => $url ) ) );
[/sourcecode]

One of those should return something.. Right? Well.. Lets look:

[sourcecode language=”php”]
array
empty
array
empty
array
empty
array
empty
[/sourcecode]

Nope, Not a thing.. What the?

Lets go check those queries again…

[sourcecode language=”sql”]
8 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘post’ ORDER BY wp_posts.post_date DESC ‘ (length=135)
1 => float 0.000998020172119
2 => string ‘get_posts’ (length=9)
9 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘page’ ORDER BY wp_posts.post_date DESC ‘ (length=135)
1 => float 0.00107502937317
2 => string ‘get_posts’ (length=9)
10 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = ‘httpdd32idau’ AND wp_posts.post_type = ‘post’ ORDER BY wp_posts.post_date DESC ‘ (length=153)
1 => float 0.00149297714233
2 => string ‘get_posts’ (length=9)
11 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.00108218193054
2 => string ‘get_page_by_path’ (length=16)
12 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.000935077667236
2 => string ‘get_page_by_path’ (length=16)
13 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = ‘0’) AND wp_posts.post_type = ‘page’ ORDER BY wp_posts.post_date DESC ‘ (length=137)
1 => float 0.000837087631226
2 => string ‘get_posts’ (length=9)
[/sourcecode]

Well, Let me first say, No idea why the last case has caused 3 queries (which are near unique), But thats not the interesting part.. Notice the post_type? Its no longer set to our requested ‘custom_type‘ oops, Lets go back and check that code, Wait! I did specify it!.

Eugh. Thank you WP_Query, Of course you know better than I do, Sorry i questioned your judgement and requested something else!

Time to hook in and tell WP_Query I know best..

[sourcecode language=”php”]
function stupid_post_type_custom_type($query) {
if ( isset($query->query_vars[‘post_type’]) && ‘custom_type’ == $query->query_vars[‘post_type’] )
$query->is_page = $query->is_single = $query->is_attchment = false;
}
$url = ‘http://dd32.id.au/’;

add_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘p’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘page_id’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘name’ => $url ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘pagename’ => $url ) ) );
remove_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
[/sourcecode]

WooHoo!

[sourcecode language=”php”]
array
0 =>
object(stdClass)[131]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168’ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
array
0 =>
object(stdClass)[133]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168’ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
array
0 =>
object(stdClass)[133]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06’ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06’ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168’ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
array
empty
[/sourcecode]

Wait!, Why is that last case still returning nothing?

Query time again..

[sourcecode language=”sql”]
8 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=142)
1 => float 0.00179696083069
2 => string ‘get_posts’ (length=9)

11 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=142)
1 => float 0.000961065292358
2 => string ‘get_posts’ (length=9)
12 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = ‘httpdd32idau’ AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=160)
1 => float 0.00102686882019
2 => string ‘get_posts’ (length=9)
13 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.00131893157959
2 => string ‘get_page_by_path’ (length=16)
14 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.00103116035461
2 => string ‘get_page_by_path’ (length=16)
15 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = ‘0’) AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=144)
1 => float 0.00140690803528
2 => string ‘get_posts’ (length=9)
[/sourcecode]

Ok, Seems using ‘pagename’ query parameter just isnt going to work, It’s been hard coded to work off ‘page’ or ‘attachment’ regardless, And when it finally does fall through to using custom_type.. It’s forgotten it was using pagename, and instead, is trying to use an ID..

Moral of the story? the parse_query hook is your friend; But make sure to only modify those queries which you’re using, and not all the core WP_Query queries too..

The working code:

[sourcecode language=”php”]
function stupid_post_type_custom_type($query) {
if ( isset($query->query_vars[‘post_type’]) &amp;&amp; ‘custom_type’ == $query->query_vars[‘post_type’] )
$query->is_page = $query->is_single = $query->is_attchment = false;
}
$url = ‘http://dd32.id.au/’;

add_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘name’ => $url ) ) );
remove_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
[/sourcecode]

EDIT: ARGH. Ok, WP/the Syntax Highlighter plugin have had a war, They dont like the idea of not touching stuff within the sourcecode shortcode.. I’m pretty sure i had a Trac ticket for that….