19

I'm using the TwentyTen theme to create a child theme, but I can't seem to get rid of the 'One column, no sidebar' page template that is in the TwentyTen parent theme.

I thought just copying it over and deleting the contents would do the trick, but it seems not. Does anyone know how to do this? I'm sure it's very simple.

Thanks

osu

6 Answers 6

11

Overriding that template would be much easier than getting rid of it. Just the way logic goes.

I make no claim it's efficient idea (late here), but this would get it nuked from edit screen:

add_action('admin_head-post.php','remove_template');

function remove_template() {

    global $wp_themes;

    get_themes();
    $templates = &$wp_themes['Twenty Ten']['Template Files'];
    $template = trailingslashit( TEMPLATEPATH ).'onecolumn-page.php';
    $key = array_search($template, $templates);
    unset( $templates[$key] );
}
6
  • Thanks for this, that looks like a good solution - when you say overriding the template, do you mean just including a one column template in there anyway? Or do you mean overriding it with a template that I want to actually use (i.e. call it One Column but it actually has 2 or 3 columns?)?
    – Osu
    Apr 1, 2011 at 11:49
  • @Osu I meant overriding with your own similar template. As far as logic goes it is easy for child theme to change and add to templates of parent theme, but it is hard to disable them. Basically child theme is supposed to do more than parent theme, not less. And code logic follows this principle.
    – Rarst
    Apr 1, 2011 at 12:24
  • ah, ok. Thanks for clearing that up. I'll create a one col template for them then. Cheers
    – Osu
    Apr 5, 2011 at 9:42
  • For anyone that wants to remove the theme from the dropdown list using jQuery, then this is another approach (not sure if it's the best way though): pastie.org/3710683
    – Osu
    Apr 1, 2012 at 20:06
  • 2
    @brasofilo theme-related internals went through major refactoring and API changes in 3.4, so plenty of older stuff won't work
    – Rarst
    Jul 9, 2012 at 21:46
38

WordPress 3.9 introduces a theme_page_templates filter.

The example below from a Twenty Fourteen child theme functions.php shows how to remove the "Contributor Page" template:

function tfc_remove_page_templates( $templates ) {
    unset( $templates['page-templates/contributors.php'] );
    return $templates;
}
add_filter( 'theme_page_templates', 'tfc_remove_page_templates' );

For all other post-types (like "post" and custom post-types) you can use the more generic theme_{$post_type}_templates filter (see docs).

add_filter('theme_page_templates', 'tfc_remove_page_templates');
add_filter('theme_post_templates', 'tfc_remove_page_templates');
add_filter('theme_mycustomposttype_templates', 'tfc_remove_page_templates');
1
  • 7
    This should be the updated accepted answer for WP 3.9+ Dec 18, 2015 at 20:25
9

Expanding on @Rarst's answer, here's a more generic approach that is not tied to a specific theme, but can be used inside your own child theme's functions.php to nuke any parent theme page templates you want to get rid of.

function remove_template( $files_to_delete = array() ){
    global $wp_themes;

    // As convenience, allow a single value to be used as a scalar without wrapping it in a useless array()
    if ( is_scalar( $files_to_delete ) ) $files_to_delete = array( $files_to_delete );

    // remove TLA if it was provided
    $files_to_delete = preg_replace( "/\.[^.]+$/", '', $files_to_delete );

    // Populate the global $wp_themes array
    get_themes();

    $current_theme_name = get_current_theme();

    // Note that we're taking a reference to $wp_themes so we can modify it in-place
    $template_files = &$wp_themes[$current_theme_name]['Template Files'];

    foreach ( $template_files as $file_path ){
        foreach( $files_to_delete as $file_name ){
            if ( preg_match( '/\/'.$file_name.'\.[^.]+$/', $file_path ) ){
                $key = array_search( $file_path, $template_files );
                if ( $key ) unset ( $template_files[$key] );
            }
        }
    }
}

So you can use it in your child theme's functions.php file like so:

add_action( 'admin_head-post.php', 'remove_parent_templates' );

function remove_parent_templates() {
    remove_template( array( "showcase.php", "sidebar-page" ) );
}

Here I'm just illustrating that you don't have to pass the ".php" part if you don't want to.

Or: remove_template( "sidebar-page" ); - you don't need to pass an array if you want to modify only a single file.

6

There's a new filter in WP core (3.9) to remove page templates. It can be used from child themes.

Here's how to achieve this in TwentyTen (tested on WP 3.9):

add_filter( 'theme_page_templates', 'my_remove_page_template' );
    function my_remove_page_template( $pages_templates ) {
    unset( $pages_templates['onecolumn-page.php'] );
    return $pages_templates;
}

https://core.trac.wordpress.org/changeset/27297

http://boiteaweb.fr/theme_page_templates-hook-semaine-16-8033.html

2
  • A link offsite becomes useless if the link changes or gets taken down. This also makes no attempt to actually answer the question
    – Tom J Nowell
    Apr 17, 2014 at 22:25
  • Fair enough, example added. Apr 18, 2014 at 12:30
1

Since previous answers no longer work here in current versions of WordPress and there was a related question which I just answered (April 2013) using a PHP output buffer I figured I'd post a link to that answer.

Also just published the Omit Parent Theme Page Templates plugin that filters out all parent theme page templates from the dropdown list of templates in the Page Attributes metabox when adding or editing a WordPress "Page."

0

July 10, 2012 - WordPress 3.4.1

Previous answers are not working and as Rarst said in a comment:

theme-related internals went through major refactoring and API changes in 3.4, so plenty of older stuff won't work

Quick and Dirty jQuery Solution

add_action('admin_head', 'wpse_13671_script_enqueuer');

function wpse_13671_script_enqueuer() {
    global $current_screen;

    /**
     * /wp-admin/edit.php?post_type=page
     */
    if('edit-page' == $current_screen->id) 
    {
        ?>
        <script type="text/javascript">         
        jQuery(document).ready( function($) {
            $("a.editinline").live("click", function () {
                var ilc_qe_id = inlineEditPost.getId(this);
                setTimeout(function() {
                        $('#edit-'+ilc_qe_id+' select[name="page_template"] option[value="showcase.php"]').remove();  
                    }, 100);
            });

            $('#doaction, #doaction2').live("click", function () {
                setTimeout(function() {
                        $('#bulk-edit select[name="page_template"] option[value="showcase.php"]').remove();  
                    }, 100);
            });       
        });    
        </script>
    <?php
    }

    /**
     * /wp-admin/post.php?post=21&action=edit
     */
    if( 'page' == $current_screen->id ) 
    {
        ?>
        <script type="text/javascript">
        jQuery(document).ready( function($) {
            $('#page_template option[value="showcase.php"]').remove();
        });
        </script>
    <?php
    }
}

No Hook for That?

If I followed the correct path, this is where the "action" happens (/wp-includes/class-wp-theme.php), and looks like there's nothing here to hook on...

/**
 * Returns the theme's page templates.
 *
 * @since 3.4.0
 * @access public
 *
 * @return array Array of page templates, keyed by filename, with the value of the translated header name.
 */
public function get_page_templates() {
    // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide.
    if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) )
        return array();

    $page_templates = $this->cache_get( 'page_templates' );

    if ( ! is_array( $page_templates ) ) {
        $page_templates = array();

        $files = (array) $this->get_files( 'php', 1 );

        foreach ( $files as $file => $full_path ) {
            $headers = get_file_data( $full_path, array( 'Template Name' => 'Template Name' ) );
            if ( empty( $headers['Template Name'] ) )
                continue;
            $page_templates[ $file ] = $headers['Template Name'];
        }

        $this->cache_add( 'page_templates', $page_templates );
    }

    if ( $this->load_textdomain() ) {
        foreach ( $page_templates as &$page_template ) {
            $page_template = $this->translate_header( 'Template Name', $page_template );
        }
    }

    if ( $this->parent() )
        $page_templates += $this->parent()->get_page_templates();

    return $page_templates;
}
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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