Cornerstone: We have compatibility!

Compatibility is so (not) overrated
By Sol in Lab

Well that didn’t take as long as I expected it to. While I still have some tests to run through, all work has been completed to make Cornerstone compatible with WordPress 3.0!  I was expecting this to take at least 2-3 days due to the amount of code I had to check, but after finishing what I had scheduled for today, I decided to just keep chugging along and ended up finishing everything on my list without much delay.

Here’s a rundown of what I did today:

Structure

Permalink Structure

The first thing on the list was adjusting the permalink structure for posts with custom post types.  By default, the structure for posts with custom post types is /post-type/post-name/, which doesn’t cut it when posts can now be added to a specific section regardless of their post type.  What we want is for all posts to use /section-name/post-name/ as their permalink structure.  I didn’t think this would be too difficult to rectify, and thankfully it wasn’t.  A quick look at get_permalink() (which Cornerstone hooks into to filter a post’s permalink) revealed that posts with custom post types were processed separately from standard posts:

elseif ( in_array($post->post_type, get_post_types( array('_builtin' => false) ) ) )
	return get_post_permalink($post, $leavename, $sample);

So in addition to hooking into post_link for standard posts, we also need to hook into post_type_link (which is called in get_post_permalink()). Thankfully, both filter hooks pass the default permalink along with the current post’s data (except that post_link supplies the entire post object while post_type_link only supplies the post’s ID) so the same handler can be used for both:

add_filter('post_link', $this->m('post_link'), 10, 2); //Standard posts
add_filter('post_type_link', $this->m('post_link'), 10, 2);  //Custom post types

With this additional hook added, posts with custom post types now have /section-name/post-name/ as their permalink structure.

Post Sections

Next on my list was providing the UI on the edit forms for custom post types to select the section the post should be saved to.  Prior to WordPress 3.0, I added the section selector to the edit form sidebar by hooking into the do_meta_boxes action. This works exactly as it should on the edit form for custom post types in WordPress 3.0, save for one difference– the action hook now passes the post type of the post currently being edited (as opposed to being hardcoded as “post” in earlier versions of WordPress). Since we only wanted the section selector to be added to the sidebar of the post edit form, that’s exactly what the handler looked for before adding the section selector meta box:

if ( 'post' == $type && 'side' == $context )
	add_meta_box($this->add_prefix('section'), 'Section', $this->m('admin_post_sidebar_section'), 'post', 'side', 'high');

Since the post type can now be variable, the condition for adding a the section selector meta box needed to be expanded a bit:

$child_types = get_post_types(array('show_ui' => true, '_builtin' => false));
$child_types[] = 'post';
$side_context = 'side';
$priority = 'high';
if ( in_array($type, $child_types) && $side_context == $context )
	add_meta_box($this->add_prefix('section'), __('Section'), $this->m('admin_post_sidebar_section'), $type, $context, $priority);

Basically, all custom post types that would have an edit form are retrieved, the “post” post type is added to the array of possible post types, and a check is performed to see if the current post type is included in this array. If so, the meta box is added and the section selector is displayed on edit form’s sidebar. I also took this opportunity to move some of the values in the add_meta_box call out into separate variables to further simplify future maintenance.

Taxonomies


I honestly thought it would take longer than it did to go through and fix the compatibility issues with permalinks and section selection so that was really all I had intended to work on today.  After finishing them so quickly, I decided that I would work on getting the rest of the edit form for custom post types to work properly.  The first thing was adding access to the standard post taxonomies (specifically, categories and post tags) on custom post type edit forms.

Once again, I thought I was in for some digging through WordPress’ code, and once again, it turned out to be incredibly simple.  WordPress provides the register_taxonomy_for_object_type() function that makes it very simple to connect a previously-registered taxonomy to a post type.  I could have used this, but WordPress also provides the ability to automatically register a taxonomy with a post type at the same time the post type itself is registered.  This is accomplished by adding a single item to the arguments array passed to register_post_type() when registering a new post type:

//...additional arguments for the post type being registered
'taxonomies' => get_object_taxonomies('post')

By using get_object_taxonomies('post'), we can be sure that any taxonomies registered to the standard “post” post type is also registered to our custom content types. In the future, I may add functionality to enable more control over which custom content types will inherit the taxonomies from WordPress’ built-in post type, but for now this makes the edit form for custom content types functional and useful for those wanting to use the same basic taxonomies with all content types.

Content Type Fields


The final thing that remained to make Cornerstone compatible with WordPress 3.0 was displaying a content type’s predefined fields on the edit form.  The implementation prior to WordPress 3.0 employed multiple hooks to make it all work (since custom post type functionality was not as fully fleshed out as it is in 3.0), but now all I needed was one hook:

add_action('do_meta_boxes', $this->m('admin_do_meta_boxes'), 10, 3);
//Build UI on post edit form

The handler is also very simple. Once it confirms that the context is appropriate for building the fields for a content type, the processing is handed off to an instance object of the content type definition which has a method to build the fields in meta boxes for output on the edit form:

function admin_do_meta_boxes($type, $context, $post) {
	//Validate $type. Should be 'post', 'page', or a custom post type for our purposes
	if ( in_array($type, array_merge(array_keys($this->get_types()), array('post', 'page'))) ) {
		//Get content type definition
		$ct =& $this->get_type($post);
		//Pass processing to content type instance
		$ct->admin_do_meta_boxes($type, $context, $post);
	}
}

Coming up next

With the compatibility work on Cornerstone out of the way, I can now continue where I left off before upgrading to WordPress 3.0 and start developing additional features and functionality for Cornerstone.  Here’s my basic plan:

  1. Complete compatibility testing, fixing any small issues I missed
  2. Develop UI for managing custom content types and their fields

The content type/field management UI will be heavy with “drag and drop” functionality to make adding and customizing content types very quick and simple.  This is one of the last major milestones I’m working towards before Cornerstone enters the public beta phase, so I am pretty excited to get started on this.

At the same time, I have a few other ideas for projects that have been dancing around in my head for the past few days and I’ve been itching to explore some of them.  I don’t intend to stay away from Cornerstone development for too long, but several of these projects will actually be using Cornerstone as the foundation of their functionality so I’ll still be working on Cornerstone as I explore these other projects.