Cornerstone: Structure Now More Structured

By Sol in Lab

WordPress has a nice little UI element below the post title field that updates to show you the post’s permalink after you have entered a title for the post.  This permalink preview is useful because it provides the user with feedback on the post they are in the process of writing.   It’s also great because it showed me that Cornerstone had a little bug.

The other day, I fired up WordPress to write a new post, added the title, and started to write the post’s content, when I noticed something strange was going on with the permalink preview:

Oops

The Bug

One of Cornerstone’s main features is Structure.  Structure allows a site to have sections and for authors to add posts to any of these sections.  When a post is added to a section, Structure makes sure the post’s permalink is logically connected to the section’s permalink.

  • Section: http://site-name.com/section-name/
  • Post: http://site-name.com/section-name/post-name/

Cornerstone adds a new permalink structure to Settings > Permalinks in the site’s admin area which lets users enable this type of logical connection between posts and sections.

  • Structured: /%postpath%/%postname%/

On this particular occasion, I had not yet selected a section for the post, which is was fortuitous because it revealed that Structure’s permalink modification was not working quite right for drafts.  In truth, it was not working at all because Structure was disabled for drafts.

function post_link($permalink, $post, $leavename = false) {
	global $wp_query;
	if ( !$this->using_post_permastruct()
		|| ( !$this->util->check_post($post) )
		|| !$this->util->property_exists($post, 'post_name')
		|| empty($post->post_name)
		|| !$this->util->property_exists($post, 'post_parent')
		|| 0 == $post->post_parent )
		return $permalink;

//	...continue modifying permalink...

According to this code, the custom permalink structure will not be used if any of the following conditions are met:

  • Cornerstone’s custom permalink structure is not enabled
  • Valid post not passed to function
  • Post has no name (e.g. drafts)
  • Post is not in a section

Since the function stopped before making any modifications to the draft post’s permalink, the permalink generated by WordPress remained.  However, since Cornerstone’s permalink structure contains a custom structure tag (%postpath%), WordPress did not know what to do with it and simply left it in the permalink (only replacing the standard %postname% tag).

Posts without sections are simply supposed to be located at the site’s root level (e.g. http://site-name.com/post-name/), but the conditions that were set to determine whether a post’s permalink should be modified were overly aggressive.  The result was that any post that wasn’t in a section would have an invalid permalink.

The Fix

Thankfully, the solution to this issue was quite apparent– simplify!

function post_link($permalink, $post, $leavename = false) {
	global $wp_query, $cnr_content_utilities;

	if ( !$this->using_post_permastruct()
		|| ( !$this->util->check_post($post) )
		|| ( empty($post->post_name) && empty($post->post_title) ) )
		return $permalink;

//	...continue modifying post permalink...

Now the custom permalink structure would be used for a post except under just a few conditions:

  • Custom permalink structure is not activated by user
  • Valid post not passed to function
  • Post has no name or title (e.g. drafts)

We check for the existence of the post’s title if there is no post name (i.e. the post’s slug) because in certain instances, the post passed to this function may not yet have a slug, but it will have a title (which we can still work with).  Only if the post has neither slug nor title will we halt further processing (since we can’t build a full permalink without at least one of those values).

Finally, since custom post types made their full debut in WordPress 3.0, we need a small addition to support them as well.  Cornerstone allows putting items with custom post types into sections as well, so the same permalink structure is used for items that have a section selected (i.e. /section-name/post-name/).  However, by default, the permalink structure for items with custom content types is /post-type/post-name/, so if an item is not in a section and it has a custom post type, then the default permalink structure should be used.

So our final conditional statement looks like:

function post_link($permalink, $post, $leavename = false) {
	global $wp_query, $cnr_content_utilities;

	if ( !$this->using_post_permastruct()
		|| ( !$this->util->check_post($post) )
		|| ( empty($post->post_name) && empty($post->post_title) )
		|| ( !$cnr_content_utilities->is_default_post_type($post->post_type) && empty($post->post_parent) ) )
		return $permalink;

//	...continue modifying post permalink...

Now post permalinks work just fine and Cornerstone’s Structure is even more structured than before.