Odeio ser o portador de más notícias, mas o WordPress codifica a funcionalidade do Modelo de Página para o tipo de postagem "página" , pelo menos na v3.0 ( Isso pode mudar em versões futuras, mas não há uma iniciativa específica que eu saiba para alterá-la ainda.Então, esta é uma das poucas vezes que estou lutando para descobrir como contornar algo sem invadir o núcleo.)
A solução que obtive é basicamente copiar o código relevante do núcleo do WordPress e modificá-lo para as nossas necessidades. Aqui estão os passos (os números de linha são da v3.0.1):
-
Copie a
page_attributes_meta_box()
function da linha 535 de/wp-admin/includes/meta-boxes.php
e modifique para adequá-la. -
Codifique um
add_meta_boxes
hook para adicionar o metabox criado em # 1. -
Copie a
get_page_templates()
function da linha 166 de/wp-admin/includes/theme.php
e modificar para se adequar. -
Copie a
page_template_dropdown()
function da linha 2550 de/wp-admin/includes/template.php
e modifique para adequá-la. -
Adicione um modelo de postagem ao seu tema.
-
Codifique um
save_post
hook para ativar o armazenamento do nome do arquivo de modelo de postagem ao salvar. -
Codifique um
single_template
hook para ativar o carregamento do modelo de postagem para as postagens associadas.
Agora, com isso!
1. Copie a função page_attributes_meta_box()
Como primeiro passo, você precisa copiar a função page_attributes_meta_box()
da linha 535 de /wp-admin/includes/meta-boxes.php
e eu escolhi renomeá-la como post_template_meta_box()
. Como você solicitou apenas modelos de página, omiti o código para especificar uma postagem pai e para especificar a ordem que torna o código muito mais simples. Eu também escolhi usar postmeta para isso em vez de tentar reutilizar a propriedade de objeto page_template
para evitar possíveis incompatibilidades causadas pelo acoplamento não intencional. Então aqui está o código:
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. Codifique um add_meta_boxes
hook
O próximo passo é adicionar o metabox usando o add_meta_boxes
hook:
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. Copie a função get_page_templates()
Presumi que faria sentido diferenciar entre modelos de página e modelo de postagem, assim, a necessidade de uma função get_post_templates()
com base em get_page_templates()
da linha 166 de /wp-admin/includes/theme.php
. Mas, em vez de usar o marcador Template Name:
, os modelos de página que usam essa função usam um marcador Post Template:
, que você pode ver abaixo.
Eu também filtrou a inspeção de functions.php
(não sei como get_page_templates()
funcionou corretamente sem isso, mas seja qual for!) E a única coisa que resta é alterar as referências à palavra page
para post
para legibilidade de manutenção ao longo da estrada:
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. Copie a função page_template_dropdown()
Da mesma forma, copie page_template_dropdown()
da linha 2550 de /wp-admin/includes/template.php
para criar post_template_dropdown()
e simplesmente altere para chamar 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. Adicionar um modelo de postagem
O próximo passo é adicionar um modelo de postagem para teste. Usando o marcador Post Template:
mencionado na etapa nº 3, copie single.php
do seu tema para single-test.php
e adicione o seguinte cabeçalho de comentário ( certifique-se de modificar algo em single-test.php
para saber que está carregando em vez de single.php
) :
/**
* Post Template: My Test Template
*/
Depois de executar as etapas de 1 a 5, você poderá ver seu metabox "Modelos de postagem" aparecer na página do editor de postagens:
6.Codifiqueumsave_post
hook
Agoraquevocêtemoeditoraomesmotempo,precisasalvaronomedoarquivodemodelodepáginaparapostmetaquandoousuárioclicarem"Publicar". Aqui está o código para isso:
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. Codifique um single_template
hook
E, finalmente, você precisa realmente fazer com que o WordPress use seus novos modelos de postagem. Você faz isso ligando single_template
e retornando o nome do seu modelo desejado para as postagens que tiveram um atribuído:
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;
}
E é sobre isso!
OBSERVAÇÃO de que não leva em consideração Tipos de postagem personalizada , somente post_type=='post'
. Na minha opinião, endereçar tipos de postagem personalizados exigiria a diferenciação entre os diferentes tipos de postagens e, embora não excessivamente difícil, não tentei fazer isso aqui.