i’m working on somekind of wiki/encyclopedia system based on wordpress.
there are two custom post types. i’ll show my configuration for one of them:
$labels = array(
'name' => _x('Objects', 'post type general name'),
'singular_name' => _x('Object', 'post type singular name'),
'add_new' => _x('Add New', 'object'),
'add_new_item' => __('Add New Object'),
'edit_item' => __('Edit Object'),
'new_item' => __('New Object'),
'view_item' => __('View Object'),
'search_items' => __('Search Objects'),
'not_found' => __('Nothing found'),
'not_found_in_trash' => __('Nothing found in Trash'),
'parent_item_colon' => ''
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'query_var' => true,
'has_archive' => 'objects', // this is the archive-slug (could be "objects/index"!!)
'rewrite' => array( 'slug' => 'objects' ), // this is the prepended slug (like "objects/my-object")
'capability_type' => 'post',
'hierarchical' => false,
'menu_position' => null,
'supports' => array('title','thumbnail')
);
register_post_type( 'dr_object' , $args );
everything is working as expected: mysite.de/objects gives me an overview (archive-dr_object.php template), mysite.de/objects/my-object shows the object details.
to have some nice urls for the frontend editing functions, i added rewrite endpoints.
add_rewrite_endpoint('do', EP_PERMALINK | EP_PAGES ); // for do/edit, do/remove, etc
this works great for urls like mysite.de/objects/my-object/do/edit
here comes my problem:
the archives should have some editing capabilities, too. but mysite.de/objects/do/edit gives me a 404: “Page not found”.
i print_r’ed $wp_query and it looks like wp queries an attachment named “edit”
hope somebody can help me – by now i’ll stick with ugly ?do=edit urls for the archives.
thanks in advance,
hans
//update 09/03/2012
stripped code of my-plugin.php
add_action('init', 'object_register');
function object_register() {
$labels = array(
'name' => _x('Objects', 'post type general name'),
'singular_name' => _x('Object', 'post type singular name'),
'add_new' => _x('Add New', 'object'),
'add_new_item' => __('Add New Object'),
'edit_item' => __('Edit Object'),
'new_item' => __('New Object'),
'view_item' => __('View Object'),
'search_items' => __('Search Objects'),
'not_found' => __('Nothing found'),
'not_found_in_trash' => __('Nothing found in Trash'),
'parent_item_colon' => ''
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'query_var' => true,
'has_archive' => 'objects', // this is the archive-slug (could be "objects/index"!!)
'rewrite' => array( 'slug' => 'objects' ), // this is the prepended slug (like "objects/my-object")
'capability_type' => 'post',
'hierarchical' => false,
'menu_position' => null,
'supports' => array('title','thumbnail')
);
register_post_type( 'dr_object' , $args );
}
add_action('init', 'cluster_register');
function cluster_register() {
$labels = array(
'name' => _x('Cluster', 'post type general name'),
'singular_name' => _x('Cluster', 'post type singular name'),
'add_new' => _x('Add New', 'cluster'),
'add_new_item' => __('Add New Cluster'),
'edit_item' => __('Edit Cluster'),
'new_item' => __('New Cluster'),
'view_item' => __('View Cluster'),
'search_items' => __('Search Cluster'),
'not_found' => __('Nothing found'),
'not_found_in_trash' => __('Nothing found in Trash'),
'parent_item_colon' => ''
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'query_var' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'cluster' ),
'capability_type' => 'post',
'hierarchical' => false,
'menu_position' => null,
'supports' => array('title')
);
register_post_type( 'dr_cluster' , $args );
}
add_action( 'init', 'build_taxonomies', 0 );
function build_taxonomies() {
register_taxonomy( 'dr_designers', array("dr_object"), array("hierarchical" => false, "label" => "Designers", "singular_label" => "Designer", "rewrite" => array('slug' => 'designer')));
register_taxonomy( 'dr_tags', array("dr_object", "dr_cluster"), array("hierarchical" => false, "label" => "Tags", "singular_label" => "Tag", "rewrite" => array('slug' => 'tags')));
register_taxonomy( 'dr_manufactors', array("dr_object"), array("hierarchical" => false, "label" => "Manufactors", "singular_label" => "Manufactor", "rewrite" => array('slug' => 'manufactors')));
}
function dr_rewrite_settings(){
// this enables to get action form objects, cluster etc by adding sth like "objects/my-object/do/edit" -- YEAH!
add_rewrite_endpoint('do', EP_PERMALINK | EP_PAGES );
// ATTENTION: This is *only* done during plugin activation hook in this example!
// You should *NEVER EVER* do this on every page load!!
flush_rewrite_rules();
}
//register_activation_hook( __FILE__, 'dr_rewrite_settings' ); this should happen
add_action('init', dr_rewrite_settings);
as you can see – i had problem flushing the rewrite in a proper way (register_activation_hook).
apart form that i should mention that i’m using another plugin to create a fakepage: mysite.de/objects/new and it goes like this:
<?php
/**
* Plugin Name: Fake Page Plugin 2
* Plugin URI: http://scott.sherrillmix.com/blog/blogger/creating-a-better-fake-post-with-a-wordpress-plugin/
* Description: Creates a fake page without a 404 error (based on <a href="http://headzoo.com/tutorials/wordpress-creating-a-fake-post-with-a-plugin">Sean Hickey's Fake Plugin Page</a>)
* Author: Scott Sherrill-Mix
* Author URI: http://scott.sherrillmix.com/blog/
* Version: 1.1
*/
class FakePage
{
/**
* The slug for the fake post. This is the URL for your plugin, like:
* http://site.com/about-me or http://site.com/?page_id=about-me
* @var string
*/
var $page_slug = 'objects/new';
/**
* The title for your fake post.
* @var string
*/
var $page_title="New Object";
/**
* Allow pings?
* @var string
*/
var $ping_status="open";
/**
* Class constructor
*/
function FakePage()
{
/**
* We'll wait til WordPress has looked for posts, and then
* check to see if the requested url matches our target.
*/
add_filter('the_posts',array(&$this,'detectPost'));
}
/**
* Called by the 'detectPost' action
*/
function createPost()
{
/**
* What we are going to do here, is create a fake post. A post
* that doesn't actually exist. We're gonna fill it up with
* whatever values you want. The content of the post will be
* the output from your plugin.
*/
/**
* Create a fake post.
*/
$post = new stdClass;
/**
* The author ID for the post. Usually 1 is the sys admin. Your
* plugin can find out the real author ID without any trouble.
*/
$post->post_author = 1;
/**
* The safe name for the post. This is the post slug.
*/
$post->post_name = $this->page_slug;
/**
* Not sure if this is even important. But gonna fill it up anyway.
*/
$post->guid = get_bloginfo('wpurl') . "https://wordpress.stackexchange.com/" . $this->page_slug;
/**
* The title of the page.
*/
$post->post_title = $this->page_title;
/**
* This is the content of the post. This is where the output of
* your plugin should go. Just store the output from all your
* plugin function calls, and put the output into this var.
*/
$post->post_content = $this->getContent();
/**
* Fake post ID to prevent WP from trying to show comments for
* a post that doesn't really exist.
*/
$post->ID = -1;
/**
* Static means a page, not a post.
*/
$post->post_status="static";
/**
* Turning off comments for the post.
*/
$post->comment_status="closed";
/**
* Let people ping the post? Probably doesn't matter since
* comments are turned off, so not sure if WP would even
* show the pings.
*/
$post->ping_status = $this->ping_status;
$post->comment_count = 0;
/**
* You can pretty much fill these up with anything you want. The
* current date is fine. It's a fake post right? Maybe the date
* the plugin was activated?
*/
$post->post_date = current_time('mysql');
$post->post_date_gmt = current_time('mysql', 1);
add_post_meta($post->ID, '_wp_page_template', 'objects-new.php', true);
return($post);
}
function getContent()
{
return '<p>Hi there! You are viewing my fake post!</p>';
}
function detectPost($posts){
global $wp;
global $wp_query;
/**
* Check if the requested page matches our target
*/
if (strtolower($wp->request) == strtolower($this->page_slug)){ //09.03 removed: || $wp->query_vars['page_id'] == $this->page_slug
//Add the fake post
$posts=NULL;
$posts[]=$this->createPost();
/**
* Trick wp_query into thinking this is a page (necessary for wp_title() at least)
* Not sure if it's cheating or not to modify global variables in a filter
* but it appears to work and the codex doesn't directly say not to.
*/
$wp_query->is_page = true;
//Not sure if this one is necessary but might as well set it like a true page
$wp_query->is_singular = true;
$wp_query->is_home = false;
$wp_query->is_archive = false;
$wp_query->is_category = false;
//Longer permalink structures may not match the fake post slug and cause a 404 error so we catch the error here
unset($wp_query->query["error"]);
$wp_query->query_vars["error"]="";
$wp_query->is_404=false;
}
return $posts;
}
}
/**
* Create an instance of our class.
*/
new FakePage;
?>
i made two modifications to the standard plugin. maybe they interfer with the rewrite_rules? (i tried deactivating this plugin – didn’t change a thing)
1) using a “hierarchical” slug. it works but: is it allowed?
2) let the fakepage use a custom template: add_post_meta($post->ID, '_wp_page_template', 'objects-new.php', true);
(right before returning the post in createPost()
)