¿Cómo eliminar una plantilla de página del tema padre en un tema hijo?
Estoy usando el tema TwentyTen para crear un tema hijo, pero no logro deshacerme de la plantilla de página 'Una columna, sin barra lateral' que está en el tema padre TwentyTen.
Pensé que con solo copiarla y eliminar su contenido sería suficiente, pero parece que no. ¿Alguien sabe cómo hacer esto? Estoy seguro de que es muy simple.
Gracias
osu
WordPress 3.9 introduce un filtro llamado theme_page_templates
.
El siguiente ejemplo, extraído del archivo functions.php
de un tema hijo de Twenty Fourteen, muestra cómo eliminar la plantilla "Página de colaboradores":
function tfc_remove_page_templates( $templates ) {
unset( $templates['page-templates/contributors.php'] );
return $templates;
}
add_filter( 'theme_page_templates', 'tfc_remove_page_templates' );
Para todos los demás tipos de contenido (como "post" y tipos de contenido personalizados), puedes usar el filtro más genérico theme_{$post_type}_templates
(ver documentación).
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');

Anular esa plantilla sería mucho más fácil que deshacerse de ella. Así es como funciona la lógica.
No afirmo que sea una idea eficiente (es tarde aquí), pero esto eliminaría la plantilla de la pantalla de edición:
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] );
}

Gracias por esto, parece una buena solución. Cuando dices sobreescribir la plantilla, ¿te refieres a simplemente incluir una plantilla de una columna ahí de todas formas? ¿O quieres decir sobreescribirla con una plantilla que realmente quiero usar (es decir, llamarla "Una Columna" pero que en realidad tenga 2 o 3 columnas?)?

@Osu Me refería a sobreescribir con tu propia plantilla similar. En cuanto a la lógica, es fácil para un tema hijo cambiar y añadir a las plantillas del tema padre, pero es difícil desactivarlas. Básicamente, se supone que un tema hijo debe hacer más que el tema padre, no menos. Y la lógica del código sigue este principio.

Ah, vale. Gracias por aclararlo. Entonces crearé una plantilla de una columna para ellos. Saludos

Para cualquiera que quiera eliminar el tema de la lista desplegable usando jQuery, este es otro enfoque (no estoy seguro si es la mejor manera): http://pastie.org/3710683

@Rarst : ¿Alguna pista sobre por qué global $wp_themes
no está aceptando el unset
en 3.4.1?

Ampliando la respuesta de @Rarst, aquí hay un enfoque más genérico que no está vinculado a un tema específico, sino que puede usarse dentro del functions.php de tu tema hijo para eliminar cualquier plantilla de página del tema padre que desees quitar.
function remove_template( $files_to_delete = array() ){
global $wp_themes;
// Como conveniencia, permite usar un valor único como escalar sin envolverlo en un array() inútil
if ( is_scalar( $files_to_delete ) ) $files_to_delete = array( $files_to_delete );
// elimina la extensión si fue proporcionada
$files_to_delete = preg_replace( "/\.[^.]+$/", '', $files_to_delete );
// Rellena el array global $wp_themes
get_themes();
$current_theme_name = get_current_theme();
// Nota que estamos tomando una referencia a $wp_themes para poder modificarlo directamente
$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] );
}
}
}
}
Entonces puedes usarlo en el archivo functions.php de tu tema hijo así:
add_action( 'admin_head-post.php', 'remove_parent_templates' );
function remove_parent_templates() {
remove_template( array( "showcase.php", "sidebar-page" ) );
}
Aquí solo estoy ilustrando que no necesitas pasar la parte ".php" si no quieres.
O también: remove_template( "sidebar-page" );
- no necesitas pasar un array si solo quieres modificar un único archivo.

Hay un nuevo filtro en el núcleo de WP (3.9) para eliminar plantillas de página. Puede ser utilizado desde temas hijos.
Aquí te mostramos cómo lograrlo en TwentyTen (probado en 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

Dado que las respuestas anteriores ya no funcionan en las versiones actuales de WordPress y había una pregunta relacionada que acabo de responder (abril de 2013) usando un buffer de salida PHP, decidí publicar un enlace a esa respuesta.
También acabo de publicar el plugin Omit Parent Theme Page Templates que filtra todas las plantillas de página del tema padre en la lista desplegable de plantillas del metabox de Atributos de página al agregar o editar una "Página" de WordPress.

10 de julio de 2012 - WordPress 3.4.1
Las respuestas anteriores no funcionan y como Rarst mencionó en un comentario:
los aspectos internos relacionados con temas pasaron por una importante refactorización y cambios en la API en la versión 3.4, por lo que muchas cosas antiguas no funcionarán
Solución rápida y sencilla con jQuery
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 hay un gancho para eso?
Si seguí el camino correcto, aquí es donde ocurre la "acción" (/wp-includes/class-wp-theme.php
), y parece que no hay nada aquí para enganchar...
/**
* Devuelve las plantillas de página del tema.
*
* @since 3.4.0
* @access public
*
* @return array Arreglo de plantillas de página, indexadas por nombre de archivo, con el valor del nombre traducido del encabezado.
*/
public function get_page_templates() {
// Si arruinas tu tema actual e invalidamos tu padre, la mayoría de las cosas siguen funcionando. Déjalo pasar.
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;
}

Tiquete de Trac: http://core.trac.wordpress.org/ticket/21891
