Developing a childtheme, how to disable the parents templates?

As @toscho mentioned it is tricky. But it is doable.

Basically you need to find action hooks called before and after the template dropdown is generated and call ob_start() to initiate output buffering and ob_get_clean() to capture the buffered HTML. The 'submitpage_box' and 'edit_page_form' hooks will work for this, respectively.

After you’ve captured the buffered HTML you need to get the list of child page templates which unfortunately requires you duplicate a lot of code from WordPress because core doesn’t make make the code reusable to get the list of page templates for only the child template. You can find the code needed in the method get_child_page_templates() in the code below which is almost completely a composition of the needed code from WordPress core.

Once you have both the buffered HTML you need to get the list of child page templates required to remove the <options>s from the <select> that are not page templates from the child theme but being sure to include the 'default' option. You can do this through a complex pair of regular expressions, the preg_match() and preg_match_all() functions and a foreach() loop where you add only the HTML for the child theme’s templates to your list and then merge them back into the HTML that came before and after the list of <option>s

Package all that up into a called I called Omit_Parent_Theme_Page_Templates which you can drop into your theme’s functions.php file or include in a plugin your are building and viola, gone are the parent page templates.

Here’s the source code for my Omit_Parent_Theme_Page_Templates class that you need:

<?php
class Omit_Parent_Theme_Page_Templates {
  function __construct() {
    add_action( 'submitpage_box', array( $this, '_submitpage_box' ) );
    add_action( 'edit_page_form', array( $this, '_edit_page_form' ) );
  }
  function _submitpage_box() {
    ob_start();
  }
  function _edit_page_form() {
    $html = ob_get_clean();
    $select_regex = '<select\s*name="page_template"\s*id="page_template".*?>';
    preg_match( "#^(.*{$select_regex})(.*?)(</select>.*)$#sm", $html, $outer_match );
    preg_match_all( "#(<option\s*value="([^"]+)'.*?>(.*?)</option>)#sm", $outer_match[2], $inner_matches, PREG_SET_ORDER );
    $child_page_templates = $this->_get_child_page_templates();    
    foreach( $inner_matches as $index => $matches )
      if ( isset( $child_page_templates[$matches[2]] ) )
        $child_page_templates[$matches[2]] = $inner_matches[$index][0];

    $html = $outer_match[1] . implode( "\n", $child_page_templates ). $outer_match[3];
    echo $html;
  }
  private function _get_child_page_templates() {
    $child_page_templates = array( 'default' => true );
    $files = wp_get_theme()->get_files( 'php', 1 );
    foreach ( $files as $file => $full_path ) {
      if ( ! preg_match( '|[^]]Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) )
        continue;
      $child_page_templates[ $file ] = true;
    }
    return $child_page_templates;
  }

}
new Omit_Parent_Theme_Page_Templates();

Because WordPress doesn’t provide hooks for what you want this code is much more complex than we’d like. It uses a technique – the modification of HTML captured in the output buffer – that is generally “a hack.” But given the nature of what we’re changing I don’t think it’s very likely to break unless WordPress rearranges the id or name attributes of the <select> or fundamentally changes how page templates work, neither of which are very likely.

Of course if some other plugin decides to modify page templates too using the same technique but in an incompatible way then that plugin might break this code or vice versa.

But I doubt any of that is too likely and if you are using for your own site I would not worry about it at all however I would be slightly more worried about releasing the code in a widely distributed plugin, but only slightly. 🙂

UPDATE:

Ah what the heck. Decided to turn this into a plugin and publish this in the WordPress plugin repository, click here to access it. I guess I wasn’t worried enough not to publish it. 🙂

Leave a Comment