Incoherency In Wordpress Custom Columns - Actions vs. Filters

Wordpress coding practices sometimes baffle me.

Custom Columns for posts / pages / users / categories are very important to me as a plugin developer who likes to hack into the Wordpress interface rather than creating his own menus in the wp-admin panel! But these days I noticed Wordpress 2.7.1 is broken in terms of custom_columns. Custom columns work for posts and pages but they don't for categories and users. You can add them but they are not even called in the row listings: user_row function and _cat_row function.
Custom Columns are easy to use. If they are actions, you add them like this:

function categories_columns($columns){ $columns['custom'] = 'Custom'; return $columns; }
add_filter( 'manage_categories_columns', 'categories_columns );

and you fill them like this:

function categories_column($col, $id){ echo 'action style echo friendly'; }
add_action( 'manage_categories_custom_column', 'categories_column' );

but if they are filters:

function categories_column($col, $id){ return 'filter style echo un-friendly'; }
add_filter( 'manage_categories_custom_column', 'categories_column' );

Fixing The Lack Of Users/Categories Custom Columns

They forgot to actually call these custom columns but allowed you to add them. They fixed it in the latest snapshot but if you use an older version (2.7.1 or older) you need to add the following:

#1. user_row in wp-admin/includes/template.php

The while has to end with:

break; // Very important
default:

$r .= "<td $attributes>";
$r .= apply_filters('manage_users_custom_column', '', $column_name, $user_object->ID);
$r .= "</td>";
break;

#2. _cat_row in wp-admin/includes/template.php

The while has to end with:

break; // Very important
default:
$output .= "<td $attributes>";
$output .= apply_filters('manage_categories_custom_column', '', $column_name, $category->term_id);
$output .= "</td>";
break;

#3. link_cat_row in wp-admin/includes/template.php

The while has to end with:

break; // Very important
default:
$output .= "<td $attributes>";
$output .= apply_filters('manage_link_categories_custom_column', '', $column_name, $category->term_id);
$output .= "</td>";
break;

These changes don't fix the problems I noticed and will detail below but make Wordpress actually use custom columns as it was intended to. There is still a major problem. Read below!

Understanding the Incoherency

Finally I noticed in latest SVN snapshot it was fixed but they messed up again. Both manage_pages_custom_column and manage_posts_custom_column are both actions and require your content to be echo-ed (output).

<td <?php echo $attributes ?>><?php do_action('manage_*_custom_column', $column_name, $ID); ?></td>

But manage_categories_custom_columnmanage_link_categories_custom_column and manage_users_custom_column are both filters which need to return content as string and can't just output it like the other ones. This just does not make sense. They are forcing programmers to output buffer themselves to feed complex HTML and PHP back to the filter issuer.

$r .= apply_filters('manage_*_custom_column', '', $column_name, $ID);

I'm sorry to say but this is sort of messed up and to fix this you need to alter the core ... thing that I hate most as you need to do it everytime you update Wordpress. Unless they fix it themselves and handle all manage_*_custom_column as actions so user can ouput freely without breaking the layout.

The difference between filters and actions is that filters need to return something while actions are called on the fly and can do anything. You can do anything in filters just don't expect it to work properly. You can't output in a filter: echo ''; without breaking the layout ... at least.

How do you fix this?

These are the changes to the core you need to do to convert these back to actions and output as you feel like it.

Change #1 - Users Custom Column

Occurs in wp-admin/includes/template.php. Search for manage_users_custom_column and change the line from:

$r .= apply_filters('manage_users_custom_column', '', $column_name, $user_object->ID);

to:

ob_start(); // Start ob
do_action('manage_users_custom_column', $column_name, $user_object->ID);
$res = ob_get_contents(); // Get ob contents
ob_end_clean(); // Clean ob
$r .= $res; // Append captured output

Change #2 - Categories Custom Column

Occurs in wp-admin/includes/template.php. Search for manage_categories_custom_column and change the line from:

$output .= apply_filters('manage_categories_custom_column', '', $column_name, $category->term_id);

to:

ob_start(); // Start ob
do_action('manage_categories_custom_column', $column_name, $category->term_id);
$res = ob_get_contents(); // Get ob contents
ob_end_clean(); // Clean ob
$output .= $res; // Append captured output

Change #3 - Link Categories Custom Column

Occurs in wp-admin/includes/template.php. Search for manage_categories_custom_column and change the line from:

$output .= apply_filters('manage_link_categories_custom_column', '', $column_name, $category->term_id);

to:

ob_start(); // Start ob
do_action('manage_link_categories_custom_column', $column_name, $category->term_id);
$res = ob_get_contents(); // Get ob contents
ob_end_clean(); // Clean ob
$output .= $res; // Append captured output

I do hope...

They will take my example and fix this accordingly in the core ... just to stay true to form and not have coders guess how things work everytime they use a new feature. If first two manage_(pages/posts)_custom_columns were actions keep it actions for the rest also. It's really a coders' thing to keep coherence in thoughts and code-flow.

Category: Wordpress Hacks, Wordpress Plugins

5 Responses

  1. +Dorzhi1:1 — #105 says:

    It’s useful topic, I used it for categories. Question is: how to add custom columns to tags list?

    • $@5ubliminal70:334 — #1 says:

      Get an username here. I’ll publish a fix for this later on.
      This one is missing too. You need to use manage_edit-tags_columns filter to add columns but the actual output hook does not exist and has to be added.

    • $@5ubliminal71:334 — #1 says:

      It’s actually fixed in the latest nightly build.

  2. Take that ridiculous browser check off of your page. It threw me out for using Chrome.

Leave a Reply

Comment Links are DoFollow only for registered subscribers … if comments pass moderation. Links in your comments may be slaughtered, hijacked or removed.