Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

So I'm creating a plugin to create buildings that list condos for sale. The simplest way to do this was to just create a custom post type for the buildings and then the listings but I'm now stuck on how to display them in an archive. I've done something similar while developing themes where I would just create a archive-my_post_type.php and single-my_post_type.php but I don't know how to anticipate how themes could be developed.

I found an answer on stack overflow that allows you to hijack the chosen template but I'm afraid template files might be more than just get_header() and the_content() etc...

What is considered best practice for this sort of thing? Do I just grab get_template_part_content and replace it with my custom loop? Or hijack the chosen template like the answer above and hope for the best?

share|improve this question
    
The best practice for a plugin is not not directly mess with template output because you cannot guess how 1 million themes are doing things and you will make everyone angry. Create a short-code or instead of a plugin make a theme. –  Wyck Feb 26 '13 at 6:51
    
Okay so how would you go about linking to a single entry from your archive of entries using shortcodes? The only thing I can think of is using GET variables and setting up a config page to tell my plugin which page is holding the single item entry... I don't find that particularly elegant. –  Gazillion Feb 26 '13 at 15:44
add comment

1 Answer 1

up vote 4 down vote accepted

Include your template files in your plugin. I stick mine in /plugin/templates.

You need to hook into template location for that template:

add_filter('archive_template', 'yourplugin_get_custom_archive_template');

function yourplugin_get_custom_archive_template($template) {
    global $wp_query;
    if (is_post_type_archive('yourCPT')) {
        $templates[] = 'archive-yourCPT.php';
        $template = yourplugin_locate_plugin_template($templates);
    }
    return $template;
}

Rinse and repeat with the appropriate checks for each template you want to implement (single, taxonomy etc).

function yourplugin_locate_plugin_template($template_names, $load = false, $require_once = true ) {
    if (!is_array($template_names)) {
        return '';
    }
    $located = '';  
    $this_plugin_dir = WP_PLUGIN_DIR . '/' . str_replace( basename(__FILE__), "", plugin_basename(__FILE__));
    foreach ( $template_names as $template_name ) {
        if ( !$template_name )
            continue;
        if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
            $located = STYLESHEETPATH . '/' . $template_name;
            break;
        } elseif ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
            $located = TEMPLATEPATH . '/' . $template_name;
            break;
        } elseif ( file_exists( $this_plugin_dir . '/templates/' . $template_name) ) {
            $located =  $this_plugin_dir . '/templates/' . $template_name;
            break;
        }
    }
    if ( $load && $located != '' ) {
        load_template( $located, $require_once );
    }
    return $located;
}

Doing it this way means that WP will look in the theme first for your templates, but will fall back to the plugin's templates folder if not found in your theme. If users want to modify the templates to fit their theme, they can simply copy them to their theme's folder.

If you want to be really clever about it, you can force a check for the templates in their theme folder and load some default styles if they're using the plugin's copy of the templates:

add_action('switch_theme', 'yourplugin_theme_check');
add_action('wp_enqueue_scripts', 'yourplugin_css');


function yourplugin_css() {
    if(get_option('yourplugin-own-theme') != true && !is_admin()) {
    wp_enqueue_style('yourplugin-styles', plugins_url('/css/yourplugin.css', __FILE__));
    }
}

function yourplugin_theme_check() {
    if(locate_template('archive-yourCPT.php') != '' && locate_template('single-yourCPT.php') != '' && locate_template('taxonomy-yourTaxonomy.php') != '' && locate_template('taxonomy-anotherTaxonomy.php') != '') {
    update_option('yourplugin-own-theme', true);
     }   
     else {
     update_option('yourplugin-own-theme', false);
     }
}
share|improve this answer
    
I suggest using plugin_dir_path, get_stylesheet_directory, and get_template_directory instead of those constants. the last two will be deprecated eventually. also why not use locate_template function within the locate plugin template function? –  Milo Mar 7 '13 at 15:19
    
I figured the constants were still kosher, as they're still used in locate_template as of 3.5.1. –  Chris Cox Mar 7 '13 at 15:34
    
+1 but you don't need to store an option - just check the template WordPress has chosen in the filter. More generally template_include can be used. (See github.com/stephenharris/Event-Organiser/blob/1.7.3/includes/… ) –  Stephen Harris Mar 7 '13 at 19:21
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.