Created
November 5, 2011 23:16
-
-
Save mikeschinkel/1342165 to your computer and use it in GitHub Desktop.
Plugin demonstrates how to route parent post/child post URLs WordPress 3.3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: MMC Parks and Features | |
* Description: This plugin demonstrates how to route parent/child URLs like http://example.com/parks/yosemite/half-dome/in WordPress 3.3 | |
* Author: Mike Schinkel | |
* Author URL: http://about.me/mikeschinkel | |
* Notes: | |
* To answer http://lists.automattic.com/pipermail/wp-hackers/2011-November/041486.html | |
* Assumes a metabox that sets $post->post_parent field for a park feature with it's park's $post->ID. | |
* | |
*/ | |
class MMC_Parks_and_Features { | |
static $PARK_FEATURE_URL_REGEX = 'parks/([^/]*)/([^/]*)/?'; | |
static function on_load() { | |
add_action( 'init', array( __CLASS__, 'init' ) ); | |
add_filter( 'request', array( __CLASS__, 'request' ) ); | |
add_filter( 'post_type_link', array( __CLASS__, 'post_type_link' ), 10, 4 ); | |
register_activation_hook( __FILE__, array( __CLASS__, 'activate_activate' ) ); | |
} | |
static function activate_activate() { | |
add_rewrite_rule( | |
self::$PARK_FEATURE_URL_REGEX, | |
'index.php?post_type=mmc_park_feature&mmc_park_qv=$matches[1]&mmc_park_feature_qv=$matches[2]', | |
'top' | |
); | |
flush_rewrite_rules(); | |
} | |
/** | |
* Changes the permalink type for any post whose post_type is 'mmc_park_feature' | |
* | |
* @param string $link | |
* @param object $post | |
* @param bool $leavename | |
* @param string $sample | |
* @return string | |
*/ | |
static function post_type_link( $link, $post, $leavename, $sample ) { | |
if ( 'mmc_park_feature' == $post->post_type ) { | |
$parent = get_post( $post->post_parent ); | |
$parent_slug = isset( $parent->post_name ) ? $parent->post_name : '%park%'; | |
$page_slug = $sample ? '%postname%' : $post->post_name; | |
$link = preg_replace( '#^(https?://[^/]+/).*$#', "$1parks/{$parent_slug}/{$page_slug}/", $link ); | |
} | |
return $link; | |
} | |
/** | |
* Test to make sure the URL is valid per the specified park and park feature referenced in the URL. | |
* | |
* @param $query_vars | |
* @return array | |
*/ | |
static function request( $query_vars ) { | |
global $wp; | |
/** | |
* Trigger this test if the match URL rewrite rule is the one added by this plugin | |
*/ | |
if ( $wp->matched_rule == self::$PARK_FEATURE_URL_REGEX ) { | |
/** | |
* Lookup the park's post | |
*/ | |
$park = get_page_by_path( $query_vars['mmc_park_qv'], OBJECT, 'mmc_park' ); | |
/** | |
* Lookup the park feature's post, scoped to the park | |
*/ | |
$park_feature_query = new WP_Query( array( | |
'name' => $query_vars['mmc_park_feature_qv'], | |
'post_type' => 'mmc_park_feature', | |
'fields' => 'ids', | |
'post_parent' => $park->ID, | |
'posts_per_page' => 1, | |
'suppress_filters' => true, | |
)); | |
/** | |
* If the park feature was not found for the park, trigger 404 error. | |
*/ | |
if ( 0 == count( $park_feature_query->posts ) ) { | |
$query_vars = array( 'error' => '404' ); | |
} | |
} | |
return $query_vars; | |
} | |
/** | |
* Register both mmc_park and mmc_park_feature post types. | |
* | |
* Note: I mostly copied this code from the question, I would typically use a helper function for labels. | |
* | |
* @return void | |
*/ | |
static function init() { | |
/** | |
* Add the rewrite rule to be checked before other rewrite rules (i.e. 'top') | |
*/ | |
register_post_type( 'mmc_park', array( | |
'labels' => array( | |
'name' => _x( 'Parks', 'mmc_pack' ), | |
'singular_name' => _x( 'Park', 'mmc_pack' ), | |
'add_new' => _x( 'Add New', 'mmc_pack' ), | |
'add_new_item' => _x( 'Add New Park', 'mmc_pack' ), | |
'all_items' => _x( 'Parks', 'mmc_pack' ), | |
'edit_item' => _x( 'Edit Park', 'mmc_pack' ), | |
'new_item' => _x( 'New Park', 'mmc_pack' ), | |
'view_item' => _x( 'View Park', 'mmc_pack' ), | |
'search_items' => _x( 'Search Parks', 'mmc_pack' ), | |
'not_found' => _x( 'No Parks found', 'mmc_pack' ), | |
'not_found_in_trash' => _x( 'No Parks found in Trash', 'mmc_pack' ), | |
'parent_item_colon' => _x( 'Parent Park', 'mmc_pack' ), | |
'menu_name' => _x( 'Parks', 'mmc_pack' ), | |
), | |
'hierarchical' => true, | |
'description' => '', | |
'supports' => array( 'title', 'editor', 'author', 'revisions', | |
'custom-fields', 'comments', 'thumbnail' ), | |
'public' => true, | |
'show_ui' => true, | |
// 'show_in_menu' => 'mmc_menu', | |
'show_in_nav_menus' => true, | |
'publicly_queryable' => true, | |
'exclude_from_search' => false, | |
'has_archive' => true, | |
'query_var' => 'mmc_park_qv', | |
'can_export' => true, | |
'rewrite' => array( 'slug' => 'parks', 'with_front' => false ), | |
'capability_type' => 'page' | |
)); | |
register_post_type( 'mmc_park_feature', array( | |
'labels' => array( | |
'name' => _x( 'Features', 'mmc_park_feature' ), | |
'singular_name' => _x( 'Feature', 'mmc_park_feature' ), | |
'add_new' => _x( 'Add New', 'mmc_park_feature' ), | |
'add_new_item' => _x( 'Add New Feature', 'mmc_park_feature' ), | |
'all_items' => _x( 'Features', 'mmc_park_feature' ), | |
'edit_item' => _x( 'Edit Feature', 'mmc_park_feature' ), | |
'new_item' => _x( 'New Feature', 'mmc_park_feature' ), | |
'view_item' => _x( 'View Feature', 'mmc_park_feature' ), | |
'search_items' => _x( 'Search Features', 'mmc_park_feature' ), | |
'not_found' => _x( 'No Features found', 'mmc_park_feature' ), | |
'not_found_in_trash' => _x( 'No Features found in Trash', 'mmc_park_feature' ), | |
'parent_item_colon' => _x( 'Parent Feature', 'mmc_park_feature' ), | |
'menu_name' => _x( 'Features', 'mmc_park_feature' ), | |
), | |
'hierarchical' => true, | |
'supports' => array( 'title', 'permalink', 'editor', 'author', 'revisions', 'custom-fields', 'comments', 'thumbnail' ), | |
'public' => true, | |
'show_ui' => true, | |
// 'show_in_menu' => 'mmc_menu', | |
'show_in_nav_menus' => true, | |
'publicly_queryable' => true, | |
'exclude_from_search' => false, | |
'has_archive' => true, | |
'query_var' => 'mmc_park_feature_qv', | |
'can_export' => true, | |
'rewrite' => array( 'slug' => 'features', 'with_front' => false ), | |
'capability_type' => 'page' | |
)); | |
} | |
} | |
MMC_Parks_and_Features::on_load(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment