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.

I've been looking around for the past couple hours for a way to create a custom page template from within a plugin but haven't had any luck yet.

What I am specifically trying to do is add an option to the list of available page templates when editing a page, and not using some other method like if( is_page( 'page-slug' ) ) { /* etc */ }

Is there a global variable I can modify to do this?

Edit:

I'm using this code currently, based on the link @m0r7if3r gave me in a comment, the problem is it will run this function when viewing the page, but not when editing the page (to populate the dropdown list with the page templates):

class JW_SiteGrader {

    private static $instance;

    private function __construct() {


        add_action( 'template_redirect', array( &$this, 'sitegrader_template_redirect' ), 20 );

    }

    public static function getInstance() {

        // Return the class data in a Singleton fashion
        if (self::$instance == null)
            self::$instance = new JW_SiteGrader();
        return self::$instance;

    }

    public function sitegrader_template_redirect() {

        add_filter( 'page_template', array( &$this, 'sitegrader_page_template' ), 10, 1 );

    }

    public function 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;

            } else if ( file_exists( TEMPLATEPATH . '/' . $template_name ) ) {

                $located = TEMPLATEPATH . '/' . $template_name;
                break;

            } else if ( file_exists( $this_plugin_dir .  $template_name ) ) {

                $located =  $this_plugin_dir . $template_name;
                break;

            }

        }

        if ( $load && '' != $located )
            load_template( $located, $require_once );

        return $located;
    }

    public function sitegrader_page_template( $template ) {

        $object = get_queried_object();

        if ( 'page' == $object->post_type ) {

            // New 
            $templates[] = "page-sitegrader.php";
            // Like in core
            $templates[] = "page-{$object->post_type}.php";
            $templates[] = "page.php";

            return locate_template( $templates );  

        }

        // return apply_filters('page_template', $template);
        return $template;
    }

}

Edit 2:

It seems that this functionality will be released in a future update, I read quite a few trac tickets about this and there has been some discussion but no real answer (hoping for 3.4). Will list trac tickets URLs here in a bit.

Edit 3:

The code above works, BUT, the only issue I'm having at this point is there's no template being added to the dropdown list when editing/adding a new page. I'm trying a few things and will update my question soon.

share|improve this question
2  
Have you tried something like this? –  m0r7if3r Feb 13 '12 at 16:21
    
@m0r7if3r (If you try that, please leave a message how it worked out - Thanks!) –  kaiser Feb 14 '12 at 1:59
    
@kaiser I tried the code he recommended, the only missing link is to get the meta box to add the template to the dropdown list (as far as I know!). –  Jared Feb 14 '12 at 17:26
    
@Jared Look at this answer by me to a similar Q and the related trac tickets on the bottom of the a. Ad your code) If it's not showing on every page, then you're using the wrong hooks to run the instance. Which hooks are you using? –  kaiser Feb 14 '12 at 21:41
    
@kaiser I'm using the page_template hook, the code above in my edit is what's currently being used. Do I need to use the template_redirect hook and then add the page_template filter in there? –  Jared Feb 14 '12 at 22:22

5 Answers 5

up vote 3 down vote accepted

Filters? Anyone?

There's no filter there to help: page_template_dropdown($template); is used to build the drop down and it's not filterable.

Sneaking into the Templates Array?

To build the drop downs contents, the core meta box uses get_page_templates(). From inside, the function looks like the following:

$themes = get_themes();
$theme = get_current_theme();
$templates = $themes[$theme]['Template Files'];

But when looking into get_themes(); then there seams to be no possibility to intercept the list of templates. Further more we have the problem, that there's no chance to get a template from outside the themes directory…

...Faking a Theme!

The theory and it's drawbacks…

You can use register_theme_directory() to add an additional theme directory where you can place templates. So the easiest thing would be to register your plugin as themes folder too:

// Register during init hook:
register_theme_directory( plugin_dir_path( __FILE__ ).'templates' );

Note: This is where I'm not sure if it will work.

During plugin activation: Then you should place a style.css.php file inside your templates folder. This would allow you to add variables to your file. This variable would then be the parent theme. And the parent theme should simply be the currently active theme. Then update your active theme to your plugin.

Drawback #2: About the »Appearance« UI… Maybe add a note that this "Theme" is not meant to be used as actual Theme. I leave the rest of »Avoid activating this theme« stuff up to your imagination. Anyway: It should work.

Drawback #2: This trick will successfully avoid child themes. You're allowed to have one parent theme. Nothing more.

share|improve this answer
    
So I am guessing that there is no actual way to use custom page templates from any inactive theme, correct? I could register a theme directory but the templates however are not available for use unless that theme is active. –  Jared Feb 15 '12 at 21:21
1  
Not really. It's just not supposed to be and therefore a lack of core. Have you tried the link to ipstenu above? I already tried going that route but ended in a dead way - with another solution. The best bet would be to follow the tickets, push & link them wherever you are. :/ –  kaiser Feb 15 '12 at 22:34

As a suggestion for a potential work around have you considered using the WordPress file system to write a page template file from your plugin to your current active theme directory? Depending upon how much control you want over this process you can have your plugin write the file on activation and remove it on uninstall. Alternatively you could could create page template files dynamically from within your plugin UI using a form to pass certain values such as the page template name which is to appear in the dropdown box of the post edit screen. You could also in theory remove the page template from within your plugin UI at the click of a button and similarly add multiple templates for different purposes. There's a good post on using the file system over at Otto's blog. I don't have the link with me now but you can search for it.

I hope they release what you were intending to do by way of a hook in the next core release.

share|improve this answer
1  
I had a method exactly like this working before but had many issues back when I tried it, because when a user would switch themes, it would not delete the template file and if they were to copy their active theme and put it on a different site, they would risk uploading a custom template file that would not work. I know there are several workarounds for that, but I really want this to be automatic. +1 for the suggestion though. –  Jared Feb 22 '12 at 20:29
1  
Hi Jared, I was also concerned about the same issue. The only solution I could think to further extend this alternative method would be to have the plugin upon it's activation get the current theme's name then if a user deactivates/switches themes you can delete the template file from that theme and rewrite it to the newly activated theme. Take a look at this link where he created his own activation/deactivation hooks for checking themes. With a little extra code I feel this is do-able. –  userabuser Feb 23 '12 at 15:12
    
Absolutely, I think that may work. I'll give it a go and post the results in my question. Thanks for the link, it helps! –  Jared Feb 23 '12 at 18:45

I took a browse through the source, and quite shockingly there doesn't look to be a way to do this! My suggested hack would be to add a second meta box with a theme override/second theme dropdown. Then hook into this filter:

# wp-includes/theme.php line 751 in 3.3.1:
return apply_filters( "{$type}_template", locate_template( $templates ) );

to return your theme file if it's been overridden. Of course, you'd want to only add_filter if it's the post you want.

If you wanted to be fancy, you could scrap the original box and re-create it (via filters of course, not modifying core code).

I'd also suggest adding a trac ticket requesting that functionality (if there isn't one already in there for it).

share|improve this answer
1  
agree w/ suggesting this for trac. –  helgatheviking Feb 13 '12 at 13:39
    
It already seems to be in the trac: core.trac.wordpress.org/ticket/15803 –  Jared Feb 13 '12 at 21:34
1  
I just investigated this for another Q about single post type templates. You can find the Trac Tickets at the end of the answer. Let's hope for 3.4. –  kaiser Feb 14 '12 at 2:05

I have accomplished this in the past by removing the default page template metabox and then adding your own metabox. I had the new metabox use the built in get_page_templates and then added the others that I needed programatically. On a save it can can update the page template just like wordpress does.

share|improve this answer
    
Would you mind showing the full code? Currently it's only a rough concept. Thanks. –  kaiser Mar 13 '12 at 3:31

A search result with DuckDuckGo add a wordpress page template turned up the answer for me on a wpmu.org page titled WordPress Custom Page Template Tutorial.

Essentially, inside the theme directory, wp-content/themes/your-theme, copy an existing page template to a new php file name of your choice. Edit the new file, taking care to change the magic "Template Name:" property value in the comment at the top of the file.

That was all there was to it. It is possible this is a feature that post-dates the question. I am using WP 3.5 with the twenty_eleven theme.

It is also possible that there are cleaner ways to extend a theme. Edits like this might be overwritten by theme updates. Mea Culpa.

share|improve this answer
    
I need a solution to add the template to the dropdown list from a plugin, not a theme. :( –  Jared Jan 31 '13 at 23:20

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.