Ненавижу быть носителем плохих новостей, но WordPress жестко кодирует функциональность шаблона страницы в тип публикации "страница" , по крайней мере, в версии 3.0 (это может измениться в будущих версиях, но я не знаю какой-либо конкретной инициативы по ее изменению). пока что. Так что это один из немногих случаев, когда я пытаюсь понять, как обойти что-то без взлома ядра.)
Решение, которое я придумала, заключается в том, чтобы в основном скопировать соответствующий код из ядра WordPress и модифицировать его для наших нужд. Вот шаги (номера строк взяты из версии 3.0.1):
Скопируйте page_attributes_meta_box()
функцию из строки 535 /wp-admin/includes/meta-boxes.php
и измените ее в соответствии с требованиями.
Кодекс add_meta_boxes
хук, чтобы добавить метабокс, созданный в # 1.
Скопируйте get_page_templates()
функцию из строки 166 /wp-admin/includes/theme.php
и измените ее в соответствии с требованиями.
Скопируйте page_template_dropdown()
функцию из строки 2550 /wp-admin/includes/template.php
и измените ее в соответствии с требованиями.
Добавьте шаблон сообщения в вашу тему.
Код save_post
хук, чтобы включить сохранение имени файла шаблона поста при сохранении.
Код single_template
хук, чтобы разрешить загрузку шаблона сообщения для связанных сообщений.
Теперь с этим!
1. Скопируйте page_attributes_meta_box()
функцию
В качестве первого шага вам нужно скопировать page_attributes_meta_box()
функцию из строки 535, /wp-admin/includes/meta-boxes.php
и я решил переименовать ее post_template_meta_box()
. Поскольку вы запрашивали только шаблоны страниц, я пропустил код для указания родительского поста и для определения порядка, который делает код намного проще. Я также решил использовать postmeta для этого, а не пытаться повторно использовать page_template
свойство объекта, чтобы избежать и потенциальных несовместимостей, вызванных непреднамеренной связью. Итак, вот код:
function post_template_meta_box($post) {
if ( 'post' == $post->post_type && 0 != count( get_post_templates() ) ) {
$template = get_post_meta($post->ID,'_post_template',true);
?>
<label class="screen-reader-text" for="post_template"><?php _e('Post Template') ?></label><select name="post_template" id="post_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php post_template_dropdown($template); ?>
</select>
<?php
} ?>
<?php
}
2. Код add_meta_boxes
крючок
Следующим шагом является добавление метабокса с помощью add_meta_boxes
хука:
add_action('add_meta_boxes','add_post_template_metabox');
function add_post_template_metabox() {
add_meta_box('postparentdiv', __('Post Template'), 'post_template_meta_box', 'post', 'side', 'core');
}
3. Скопируйте get_page_templates()
функцию
Я предположил, что будет иметь смысл только различать шаблоны страниц и шаблоны сообщений, таким образом, необходимость в get_post_templates()
функции, основанной на get_page_templates()
строке 166 /wp-admin/includes/theme.php
. Но вместо использования Template Name:
маркера, какие шаблоны страниц используют эту функцию, Post Template:
вместо этого используется маркер, который вы можете увидеть ниже.
Я также отфильтровываюсь осмотр functions.php
(не знаю , как get_page_templates()
никогда правильно работали без этого, но что угодно!) И единственное , что осталось сделать ссылки изменения на слово page
к post
для обслуживания читаемости вниз по дороге:
function get_post_templates() {
$themes = get_themes();
$theme = get_current_theme();
$templates = $themes[$theme]['Template Files'];
$post_templates = array();
if ( is_array( $templates ) ) {
$base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) );
foreach ( $templates as $template ) {
$basename = str_replace($base, '', $template);
if ($basename != 'functions.php') {
// don't allow template files in subdirectories
if ( false !== strpos($basename, '/') )
continue;
$template_data = implode( '', file( $template ));
$name = '';
if ( preg_match( '|Post Template:(.*)$|mi', $template_data, $name ) )
$name = _cleanup_header_comment($name[1]);
if ( !empty( $name ) ) {
$post_templates[trim( $name )] = $basename;
}
}
}
}
return $post_templates;
}
4. Скопируйте page_template_dropdown()
функцию
Аналогично скопируйте page_template_dropdown()
строку 2550 /wp-admin/includes/template.php
для создания post_template_dropdown()
и просто измените ее на вызов get_post_templates()
вместо этого:
function post_template_dropdown( $default = '' ) {
$templates = get_post_templates();
ksort( $templates );
foreach (array_keys( $templates ) as $template )
: if ( $default == $templates[$template] )
$selected = " selected='selected'";
else
$selected = '';
echo "\n\t<option value='".$templates[$template]."' $selected>$template</option>";
endforeach;
}
5. Добавить шаблон сообщения
Следующим шагом является добавление шаблона сообщения для тестирования. Используя Post Template:
маркер, упомянутый в шаге 3, скопируйте single.php
из своей темы single-test.php
и добавьте следующий заголовок комментария ( обязательно измените что-то, single-test.php
чтобы вы могли сказать, что он загружается вместо single.php
) :
/**
* Post Template: My Test Template
*/
После того, как вы сделали шаги с 1 по 5, вы можете увидеть, что ваше метабокс «Шаблоны сообщений» появится на странице вашего редактора сообщений:
(источник: mikeschinkel.com )
6. Код save_post
крючка
Теперь, когда у вас есть редактор, вы должны сохранить имя файла шаблона страницы в postmeta, когда пользователь нажимает «Опубликовать». Вот код для этого:
add_action('save_post','save_post_template',10,2);
function save_post_template($post_id,$post) {
if ($post->post_type=='post' && !empty($_POST['post_template']))
update_post_meta($post->ID,'_post_template',$_POST['post_template']);
}
7. Код single_template
крючок
И, наконец, вам нужно заставить WordPress использовать ваши новые шаблоны сообщений. Вы делаете это, перехватывая single_template
и возвращая желаемое имя шаблона для тех сообщений, которым назначен один:
add_filter('single_template','get_post_template_for_template_loader');
function get_post_template_for_template_loader($template) {
global $wp_query;
$post = $wp_query->get_queried_object();
if ($post) {
$post_template = get_post_meta($post->ID,'_post_template',true);
if (!empty($post_template) && $post_template!='default')
$template = get_stylesheet_directory() . "/{$post_template}";
}
return $template;
}
И это все!
Примечание , что я не принимать во внимание ТАМОЖЕННЫЙ ПОСТ типы , только post_type=='post'
. По моему мнению, обращение к пользовательским типам постов потребовало бы разграничения между разными типами постов, и, хотя это было не слишком сложно, я не пытался сделать это здесь.