Nienawidzę być nosicielem złych wiadomości, ale WordPress zakoduje na stałe funkcjonalność szablonu strony na typ postu „stronicowego” , przynajmniej w wersji 3.0 (co może się zmienić w przyszłych wersjach, ale nie ma konkretnej inicjatywy, o której istnieniu wiem, aby to zmienić jeszcze. Więc to jeden z niewielu razy, kiedy próbuję wymyślić, jak obejść coś bez rąbania rdzenia.)
Rozwiązaniem, które wymyśliłem, jest w zasadzie skopiowanie odpowiedniego kodu z rdzenia WordPress i zmodyfikowanie go do naszych potrzeb. Oto kroki (numery linii pochodzą z wersji 3.0.1):
Skopiuj page_attributes_meta_box()
funkcję z wiersza 535 /wp-admin/includes/meta-boxes.php
i zmodyfikuj odpowiednio.
Kod add_meta_boxes
haka, aby dodać metaboks utworzony w # 1.
Skopiuj get_page_templates()
funkcję z wiersza 166 /wp-admin/includes/theme.php
i zmodyfikuj w celu dopasowania.
Skopiuj page_template_dropdown()
funkcję z wiersza 2550 /wp-admin/includes/template.php
i zmodyfikuj w celu dopasowania.
Dodaj szablon posta do swojego motywu.
Kod save_post
haka, aby umożliwić zapisywanie nazwy pliku szablonu postu po zapisaniu.
Kod single_template
haka, aby umożliwić ładowanie szablonu postu dla powiązanych postów.
Teraz z tym!
1. Skopiuj page_attributes_meta_box()
funkcję
Naszym pierwszym krokiem jest skopiowanie page_attributes_meta_box()
funkcji z wiersza 535 /wp-admin/includes/meta-boxes.php
i postanowiłem ją zmienić post_template_meta_box()
. Ponieważ poprosiłeś tylko o szablony stron, pominąłem kod określający post nadrzędny i określający kolejność, co znacznie upraszcza kod. Zdecydowałem się również użyć do tego postmeta, niż próbować ponownie użyć page_template
właściwości obiektu, aby uniknąć potencjalnych niezgodności spowodowanych przypadkowym sprzężeniem. Oto kod:
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. Kod add_meta_boxes
hak
Następnym krokiem jest dodanie metaboksu za pomocą add_meta_boxes
haka:
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. Skopiuj get_page_templates()
funkcję
Zakładałem, że sensowne byłoby jedynie rozróżnienie między szablonami strony a szablonem postu, dlatego potrzeba get_post_templates()
funkcji opartej na get_page_templates()
linii 166 z /wp-admin/includes/theme.php
. Ale zamiast używać Template Name:
znacznika, którego szablony stron używają, ta funkcja używa Post Template:
znacznika, który można zobaczyć poniżej.
Odfiltrowałem też inspekcję functions.php
(nie jestem pewien, jak to get_page_templates()
działało bez tego poprawnie, ale cokolwiek!). Pozostało mi tylko zmienić odniesienia do tego słowa w page
celu post
zapewnienia czytelności konserwacji na drodze:
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. Skopiuj page_template_dropdown()
funkcję
Podobnie skopiuj page_template_dropdown()
z linii 2550, /wp-admin/includes/template.php
aby utworzyć post_template_dropdown()
i po prostu zmień go na wywołanie get_post_templates()
zamiast:
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. Dodaj szablon posta
Następnym krokiem jest dodanie szablonu postu do testowania. Za pomocą Post Template:
znacznika wymienionego w kroku 3 skopiuj single.php
z motywu single-test.php
i dodaj następujący nagłówek komentarza ( pamiętaj, aby coś zmodyfikować, single-test.php
aby można było powiedzieć, że ładuje się zamiast single.php
) :
/**
* Post Template: My Test Template
*/
Po wykonaniu kroków od 1 do 5 na stronie edytora postów pojawi się metaboks „Szablony postów ” :
(źródło: mikeschinkel.com )
6. Kod save_post
hak
Teraz, gdy edytor jest wyrównany, musisz zapisać nazwę pliku szablonu strony na postmeta, gdy użytkownik kliknie „Publikuj”. Oto kod do tego:
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. Zakoduj single_template
hak
I wreszcie, musisz faktycznie przekonać WordPressa do korzystania z nowych szablonów postów. Robisz to, przechwytując single_template
i zwracając żądaną nazwę szablonu dla tych postów, do których przypisano jeden:
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;
}
I o to chodzi!
UWAGA , że nie bierze pod uwagę niestandardowe typy post , tylko post_type=='post'
. Moim zdaniem adresowanie niestandardowych typów postów wymagałoby rozróżnienia między różnymi typami postów i chociaż nie było to zbyt trudne, nie próbowałem tego tutaj.