Как удалить шаблон страницы родительской темы из дочерней темы?
Я использую тему TwentyTen для создания дочерней темы, но не могу избавиться от шаблона страницы 'Одна колонка, без боковой панели', который находится в родительской теме TwentyTen.
Я думал, что простое копирование и удаление содержимого сработает, но похоже, что нет. Кто-нибудь знает, как это сделать? Я уверен, что это очень просто.
Спасибо
osu
В WordPress 3.9 появился фильтр theme_page_templates
.
Пример ниже из дочерней темы Twenty Fourteen в файле functions.php
показывает, как удалить шаблон "Страница участников":
function tfc_remove_page_templates( $templates ) {
unset( $templates['page-templates/contributors.php'] );
return $templates;
}
add_filter( 'theme_page_templates', 'tfc_remove_page_templates' );
Для всех других типов записей (таких как "записи" и пользовательские типы записей) можно использовать более универсальный фильтр theme_{$post_type}_templates
(см. документацию).
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');

Переопределить этот шаблон будет гораздо проще, чем избавиться от него. Такова логика вещей.
Не утверждаю, что это эффективное решение (уже поздно), но вот как можно убрать его из экрана редактирования:
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] );
}

Спасибо за это, выглядит как хорошее решение - когда ты говоришь о переопределении шаблона, ты имеешь в виду просто включение одноколоночного шаблона в любом случае? Или ты имеешь в виду переопределение его шаблоном, который я хочу фактически использовать (т.е. назвать его "Одна колонка", но на самом деле он имеет 2 или 3 колонки?)?

@Osu Я имел в виду переопределение вашим собственным похожим шаблоном. Что касается логики, дочерней теме легко изменять и добавлять шаблоны родительской темы, но сложно их отключать. По сути, дочерняя тема должна делать больше, чем родительская, а не меньше. И логика кода следует этому принципу.

А, понятно. Спасибо за разъяснение. Тогда я создам для них одноколоночный шаблон. Спасибо

Для тех, кто хочет удалить тему из выпадающего списка с помощью jQuery, вот ещё один подход (не уверен, что это лучший способ): http://pastie.org/3710683

@Rarst: Есть какие-то предположения, почему global $wp_themes
не принимает unset
в версии 3.4.1?

Развивая ответ @Rarst, вот более универсальный подход, который не привязан к конкретной теме и может быть использован в functions.php вашей дочерней темы для удаления любых шаблонов страниц родительской темы, от которых вы хотите избавиться.
function remove_template( $files_to_delete = array() ){
global $wp_themes;
// Для удобства, разрешаем передачу одиночного значения без оборачивания в массив array()
if ( is_scalar( $files_to_delete ) ) $files_to_delete = array( $files_to_delete );
// Удаляем расширение файла, если оно было указано
$files_to_delete = preg_replace( "/\.[^.]+$/", '', $files_to_delete );
// Заполняем глобальный массив $wp_themes
get_themes();
$current_theme_name = get_current_theme();
// Обратите внимание, что мы работаем со ссылкой на $wp_themes, чтобы изменять его напрямую
$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] );
}
}
}
}
Вы можете использовать эту функцию в файле functions.php вашей дочерней темы следующим образом:
add_action( 'admin_head-post.php', 'remove_parent_templates' );
function remove_parent_templates() {
remove_template( array( "showcase.php", "sidebar-page" ) );
}
Здесь я просто показываю, что вам не обязательно указывать расширение ".php", если вы не хотите.
Или так: remove_template( "sidebar-page" );
- вам не нужно передавать массив, если нужно изменить только один файл.

В ядре WordPress (версия 3.9) появился новый фильтр для удаления шаблонов страниц. Его можно использовать в дочерних темах.
Вот как это можно реализовать в TwentyTen (протестировано на 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

Поскольку предыдущие ответы больше не работают в текущих версиях WordPress, и был связанный вопрос, на который я только что ответил (апрель 2013), используя буфер вывода PHP, я решил опубликовать ссылку на этот ответ.
Также только что опубликовал плагин Omit Parent Theme Page Templates, который исключает все шаблоны страниц родительской темы из выпадающего списка шаблонов в метабоксе "Атрибуты страницы" при добавлении или редактировании страницы WordPress.

10 июля 2012 - WordPress 3.4.1
Предыдущие решения не работают, и, как сказал Rarst в комментарии:
внутренние механизмы, связанные с темами, подверглись серьёзному рефакторингу и изменениям API в версии 3.4, поэтому многие старые решения больше не работают
Быстрое и грязное 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
}
}
Нет хука для этого?
Если я правильно проследил путь, вот где происходит "действие" (/wp-includes/class-wp-theme.php
), и похоже, что здесь не к чему подключить хук...
/**
* Возвращает шаблоны страниц темы.
*
* @since 3.4.0
* @access public
*
* @return array Массив шаблонов страниц, ключ — имя файла, значение — переведённое название шаблона.
*/
public function get_page_templates() {
// Если вы испортили текущую тему, и мы признаём ваш родительский шаблон недействительным, большинство вещей всё равно работают. Пусть будет так.
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;
}

Тикет в Trac: http://core.trac.wordpress.org/ticket/21891
