Created
November 8, 2011 02:07
-
-
Save anonymous/1346808 to your computer and use it in GitHub Desktop.
Response to https://gist.github.com/1342165
This file contains 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 | |
* Version: 2 | |
* 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/([^/]*)/([^/]*)/?'; | |
/* MMC DEBUG BEGIN */ | |
static $FEATURE_DETAIL_URL_REGEX = '^parks/([^/]*)/([^/]*)/([^/]*)/?'; | |
/* MMC DEBUG END */ | |
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, 2 ); | |
//register_activation_hook( __FILE__, array( __CLASS__, 'activate_deactivate' ) ); | |
//register_deactivation_hook( __FILE__, array( __CLASS__, 'activate_deactivate' ) ); | |
} | |
/** | |
* Changes the permalink type for any post whose post_type is 'mmc_park_feature' | |
* | |
* @param string $link | |
* @param object $post | |
* @return string | |
*/ | |
static function post_type_link( $link, $post ) { | |
if ( 'mmc_park_feature' == $post->post_type ) { | |
$parent = get_post( $post->post_parent ); | |
$link = preg_replace( '#^(https?://[^/]+/).*$#', "$1parks/{$parent->post_name}/{$post->post_name}/", $link ); | |
} | |
/* MMC DEBUG BEGIN */ | |
if ( 'mmc_feature_detail' == $post->post_type ) { | |
$parent = get_post( $post->post_parent ); | |
$grandparent = get_post( $parent->post_parent ); | |
$link = preg_replace( '#^(https?://[^/]+/).*$#', "$1parks/{$grandparent->post_name}/{$parent->post_name}/{$post->post_name}/", $link ); | |
} | |
/* MMC DEBUG END */ | |
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; | |
/* MMC DEBUG BEGIN */ | |
if ( $wp->matched_rule == self::$FEATURE_DETAIL_URL_REGEX ) { | |
$park_feature = get_page_by_path( $query_vars['mmc_park_feature_qv'], OBJECT, 'mmc_park_feature' ); | |
$feature_detail_query = new WP_Query( array( | |
'name' => $query_vars['mmc_feature_detail_qv'], | |
'post_type' => 'mmc_feature_detail', | |
'fields' => 'ids', | |
'post_parent' => $park->ID, | |
'posts_per_page' => 1, | |
'suppress_filters' => true, | |
)); | |
if ( 0 == count( $feature_detail_query->posts ) ) { | |
$query_vars = array( 'error' => '404' ); | |
} | |
} | |
/* MMC DEBUG END */ | |
/** | |
* 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') | |
*/ | |
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' | |
); | |
/* MMC DEBUG BEGIN */ | |
add_rewrite_rule( | |
self::$FEATURE_DETAIL_URL_REGEX, | |
'index.php?post_type=park_detail&mmc_park_qv=$matches[1]&mmc_park_feature_qv=$matches[2]&mmc_feature_detail_qv=$matches[3]', | |
'top' | |
); | |
/* MMC DEBUG END */ | |
register_post_type( 'mmc_park', array( | |
'labels' => array( | |
'name' => _x( 'Parks', 'mmc_park' ), | |
'singular_name' => _x( 'Park', 'mmc_park' ), | |
'add_new' => _x( 'Add New', 'mmc_park' ), | |
'add_new_item' => _x( 'Add New Park', 'mmc_park' ), | |
'all_items' => _x( 'Parks', 'mmc_park' ), | |
'edit_item' => _x( 'Edit Park', 'mmc_park' ), | |
'new_item' => _x( 'New Park', 'mmc_park' ), | |
'view_item' => _x( 'View Park', 'mmc_park' ), | |
'search_items' => _x( 'Search Parks', 'mmc_park' ), | |
'not_found' => _x( 'No Parks found', 'mmc_park' ), | |
'not_found_in_trash' => _x( 'No Parks found in Trash', 'mmc_park' ), | |
'parent_item_colon' => _x( 'Parent Park', 'mmc_park' ), | |
'menu_name' => _x( 'Parks', 'mmc_park' ), | |
), | |
'hierarchical' => true, | |
'description' => '', | |
'supports' => array( 'title', 'editor', 'author', 'revisions', | |
'custom-fields', 'comments', 'thumbnail' ), | |
'public' => true, | |
'show_ui' => true, | |
'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', 'editor', 'author', 'revisions', 'custom-fields', 'comments', 'thumbnail' ), | |
'public' => true, | |
'show_ui' => true, | |
'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' | |
)); | |
register_post_type( 'mmc_feature_detail', array( | |
'labels' => array( | |
'name' => _x( 'Details', 'mmc_feature_detail' ), | |
'singular_name' => _x( 'Detail', 'mmc_feature_detail' ), | |
'add_new' => _x( 'Add New', 'mmc_feature_detail' ), | |
'add_new_item' => _x( 'Add New Detail', 'mmc_feature_detail' ), | |
'all_items' => _x( 'Details', 'mmc_feature_detail' ), | |
'edit_item' => _x( 'Edit Detail', 'mmc_feature_detail' ), | |
'new_item' => _x( 'New Detail', 'mmc_feature_detail' ), | |
'view_item' => _x( 'View Detail', 'mmc_feature_detail' ), | |
'search_items' => _x( 'Search Details', 'mmc_feature_detail' ), | |
'not_found' => _x( 'No Details found', 'mmc_feature_detail' ), | |
'not_found_in_trash' => _x( 'No Details found in Trash', 'mmc_feature_detail' ), | |
'parent_item_colon' => _x( 'Parent Detail', 'mmc_feature_detail' ), | |
'menu_name' => _x( 'Details', 'mmc_feature_detail' ), | |
), | |
'hierarchical' => true, | |
'supports' => array( 'title', 'editor', 'author', 'revisions', 'custom-fields', 'comments', 'thumbnail' ), | |
'public' => true, | |
'show_ui' => true, | |
'show_in_nav_menus' => true, | |
'publicly_queryable' => true, | |
'exclude_from_search' => false, | |
'has_archive' => true, | |
'query_var' => 'mmc_feature_detail_qv', | |
'can_export' => true, | |
'rewrite' => array( 'slug' => 'details', 'with_front' => false ), | |
'capability_type' => 'page' | |
)); | |
} | |
} | |
MMC_Parks_and_Features::on_load(); | |
add_action( 'load-post.php', 'metabox_create' ); | |
add_action( 'load-post-new.php', 'metabox_create' ); | |
add_action( 'save_post', 'metabox_save' ); | |
function metabox_create() { | |
add_meta_box( 'mmc_post_parent', 'Parent Park', 'metabox_display', 'mmc_park_feature', 'side', 'low', array( 'parent_type' => 'mmc_park' ) ); | |
add_meta_box( 'mmc_post_parent', 'Parent Feature', 'metabox_display', 'mmc_feature_detail', 'side', 'low', array( 'parent_type' => 'mmc_park_feature' ) ); | |
} | |
function metabox_display( $post, $metabox ) { | |
global $wpdb; | |
$parent_type = $metabox['args']['parent_type']; | |
$query = "SELECT ID, post_title | |
FROM $wpdb->posts | |
WHERE post_type = '{$parent_type}' | |
AND post_status = 'publish' | |
ORDER BY post_title"; | |
$results = $wpdb->get_results( $query, OBJECT ); | |
wp_nonce_field( plugin_basename( __FILE__ ), 'mmc_post_parent_noncename' ); | |
?> | |
<select name="mmc_post_parent" id="mmc_post_parent"> | |
<option value="0"></option> | |
<?php | |
$parent_post = $post->post_parent; | |
foreach ( $results as $result ) { | |
if ( $parent_post == $result->ID ) { | |
echo '<option value="'. $result->ID . '" selected="selected">' . $result->post_title . '</option>'; | |
} else { | |
echo '<option value="'. $result->ID . '">' . $result->post_title . '</option>'; | |
} | |
} | |
?> | |
</select> | |
<?php | |
} | |
function metabox_save( $post_id ) { | |
global $post; | |
global $wpdb; | |
if ( ! wp_verify_nonce( $_POST['mmc_post_parent_noncename'], plugin_basename(__FILE__) ) ) { | |
return $post_id; | |
} | |
$data = $_POST['mmc_post_parent']; | |
$wpdb->update( $wpdb->posts, array ( 'post_parent' => $data ), array ( 'ID' => $post_id ) ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment