Adicionando Metabox e modelos de página de atributos de página à página de edição de postagens?

14

( Nota dos moderadores: o título era originalmente "Como posso adicionar o seletor" Atributos da página "e / ou" Atributos da página> Modelo "ao editor do POSTS")

O WP atualmente permite apenas a atribuição de um "modelo" para o Pages (ou seja, post_type=='page' .). Gostaria de estender essa funcionalidade a Postagens também (por exemplo post_type=='post'.)

Como posso adicionar o caixa de meta "Atributos da página" e, mais especificamente, o alternador de modelos ao editor de postagens?

Estou assumindo que este é um código que colocarei no meu functions.phppara o meu tema.

ATUALIZAÇÃO: Consegui adicionar o menu suspenso de modelos codificados no meu editor de postagem, simplesmente adicionando o html da caixa de seleção à minha caixa de meta opções personalizada existente. Aqui está o código que estou usando para isso ...

add_meta_box('categorydiv2', __('Post Options'), 'post_categories_meta_box_modified', 'post', 'side', 'high');

E aqui está a função que escreve as opções e a caixa de seleção de modelo ...

//adds the custom categories box
function post_categories_meta_box_modified() {
    global $post;
    if( get_post_meta($post->ID, '_noindex', true) ) $noindexChecked = " checked='checked'";
    if( get_post_meta($post->ID, '_nofollow', true) ) $nofollowChecked = " checked='checked'";
?>
<div id="categories-all" class="ui-tabs-panel">
    <ul id="categorychecklist" class="list:category categorychecklist form-no-clear">
        <li id='noIndex' class="popular-category"><label class="selectit"><input value="noIndex" type="checkbox" name="chk_noIndex" id="chk_noIndex"<?php echo $noindexChecked ?> /> noindex</label></li> 
        <li id='noFollow' class="popular-category"><label class="selectit"><input value="noFollow" type="checkbox" name="chk_noFollow" id="chk_noFollow"<?php echo $nofollowChecked ?> /> nofollow</label></li>
    </ul>

    <p><strong>Template</strong></p> 
    <label class="screen-reader-text" for="page_template">Post Template</label><select name="page_template" id="page_template"> 
    <option value='default'>Default Template</option> 
    <option value='template-wide.php' >No Sidebar</option>
    <option value='template-salespage.php' >Salespage</option>
    </select>
</div>
<?php
}

E, finalmente, o código para capturar os valores selecionados ao salvar ...

function save_post_categories_meta($post_id) {
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;
    $noIndex = $_POST['chk_noIndex'];
    $noFollow = $_POST['chk_noFollow'];
    update_post_meta( $post_id, '_noindex', $noIndex );
    update_post_meta( $post_id, '_nofollow', $noFollow );
    return $post_id;
}

Agora, acredito que tudo o que resta é (1) capturar o modelo selecionado e adicioná-lo à meta da postagem para esta postagem e (2) modificar index.php e single.php para que ele use o modelo escolhido.

Scott B
fonte
@ Scott B : Bem, eu escrevi toda a minha resposta antes de ver que você estava trabalhando nisso também, e parece que você tomou uma direção um pouco diferente da sua pergunta original, com suas opções de não seguir e sem índice. Espero que o que fiz ainda tenha valor para você. Caso contrário, talvez ajude os outros.
MikeSchinkel 10/10
Sim, você respondeu à pergunta. Tomei uma abordagem um pouco diferente quando percebi que não precisava analisar o diretório e poderia codificar os valores para meus modelos específicos. Eu provavelmente ainda precisarei emprestar parte do seu código para realmente fazer com que o WP use o modelo atribuído correto para a postagem.
Scott B

Respostas:

12

Odeio ser portador de más notícias, mas o WordPress codifica a funcionalidade do Modelo de Página para a "página" tipo de postagem , pelo menos na v3.0 (que pode mudar em versões futuras, mas não há uma iniciativa específica que eu saiba mudar) Portanto, esta é uma das poucas vezes em que estou lutando para descobrir como contornar algo sem invadir o núcleo.)

A solução que eu encontrei é basicamente copiar o código relevante do núcleo do WordPress e modificá-lo de acordo com nossas necessidades. Aqui estão as etapas (os números de linha são da v3.0.1):

  1. Copie a page_attributes_meta_box()função da linha 535 /wp-admin/includes/meta-boxes.phpe modifique para se adequar.

  2. Codifique um add_meta_boxes gancho para adicionar o metabox criado em # 1.

  3. Copie a get_page_templates()função da linha 166 de /wp-admin/includes/theme.php e modifique para se adequar.

  4. Copie a page_template_dropdown()função da linha 2550 de/wp-admin/includes/template.php e modifique para se adequar.

  5. Adicionar um modelo de postagem ao seu tema.

  6. Codifique um save_postgancho para permitir o armazenamento do nome do arquivo do modelo de postagem ao salvar.

  7. Codifique um single_templategancho para permitir o carregamento do modelo de postagem para as postagens associadas.

Agora vamos lá!


1. Copie o page_attributes_meta_box() função

Como nosso primeiro passo, você precisa copiar a page_attributes_meta_box()função da linha 535 /wp-admin/includes/meta-boxes.phpe escolhi renomeá-la 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. Também escolhi usar o postmeta para isso em vez de tentar reutilizar a page_templatepropriedade do objeto para evitar possíveis incompatibilidades causadas por acoplamentos não intencionais. 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_boxesgancho

O próximo passo é adicionar o metabox usando o add_meta_boxesgancho:

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 get_page_templates()função

Eu assumi que faria sentido diferenciar entre modelos de página e modelo de postagem, portanto, a necessidade de uma get_post_templates()função baseada na get_page_templates()linha 166 de /wp-admin/includes/theme.php. Mas em vez de usar oTemplate Name: marcador, os modelos de página que usam essa função usam um Post Template:marcador, que você pode ver abaixo.

Eu também filtrados inspeção de functions.php (não sei como get_page_templates()nunca funcionou corretamente sem isso, mas o que quer!) E a única coisa que resta é a referências de mudança para a palavra pagepara posta manutenção legibilidade na 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 o page_template_dropdown() função

Da mesma forma, copie page_template_dropdown()da linha 2550 de /wp-admin/includes/template.phppara criar post_template_dropdown()e simplesmente altere-a 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. Adicione um modelo de postagem

O próximo passo é adicionar um modelo de postagem para teste. Usando o Post Template:marcador mencionado na etapa # 3, copie single.phpdo seu tema para single-test.phpe adicione o seguinte cabeçalho de comentário (não se esqueça de modificar algo single-test.phppara poder dizer que ele está carregando em vez de single.php) :

/**
 * Post Template: My Test Template
 */

Depois de executar as etapas de 1 a 5, você poderá ver a metabox "Modelos de postagem " na página do editor de postagem:

Como era um Metabox de Modelos de Post quando adicionado ao WordPress 3.0
(fonte: mikeschinkel.com )

6. Codifique um save_postgancho

Agora que você tem o editor ao lado, é necessário salvar o nome do arquivo do modelo da página no postmeta quando o usuário clicar em "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_templategancho

E, finalmente, você precisa realmente obter o WordPress para usar seus novos modelos de postagem. Você faz isso conectando single_templatee retornando o nome do modelo desejado para as postagens às quais foi atribuída uma:

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 é isso!

OBSERVAÇÃO : não levei em consideração apenas os Tipos de postagem personalizadospost_type=='post' . Na minha opinião, abordar tipos de postagem personalizados exigiria diferenciação entre os diferentes tipos de postagem e, embora não seja muito difícil, não tentei isso aqui.

MikeSchinkel
fonte
Ótimo! Fui dormir com um código quase completo no meu editor, com a mesma abordagem de copiar as funções padrão do WordPress (estava completa, mas não a publicaria porque não testei). :)
sorich87
@ sorich87 - Você conhece o velho ditado: "Você dorme, perde!" Sério, brincando. Existe realmente apenas uma maneira razoável de fazê-lo funcionar, portanto, não é de admirar que seu código seja o mesmo!
MikeSchinkel
Mike, você continua surpreendendo. Muito obrigado por dedicar um tempo para resolver isso.
Scott B
@ sorich87 - Obrigado por trabalhar nisso. Eu realmente aprecio o esforço.
Scott B
1
@ Scott B : Sem problemas, feliz por poder ajudar. Procuro perguntas razoavelmente genéricas que possam ajudar muitas pessoas e tento respondê-las não apenas pela pessoa que está fazendo a pergunta, mas também pelas que possam vir depois.
115510 MikeSchinkel
0

O Wordpress permite que você adicione Meta às categorias usando um plugin:

Para fazer isso, você precisa adicionar uma das várias extensões que adicionam meta às categorias (imitando quais páginas saem da caixa), o Simple Term Meta faz o trabalho corretamente.

NB WordPress 3.x é necessário para estender categorias.

Depois disso, você pode usar:

  • add_term_meta
  • update_term_meta
  • get_term_meta

Use Functions.php para adicionar métodos para fazer o que você deseja, por exemplo

add_action('category_add_form_fields', 'category_metabox_add', 10, 1);

function category_metabox_add($tag) { ?>
    <div class="form-field">
        <label for="image-url"><?php _e('Image URL') ?></label>
        <input name="image-url" id="image-url" type="text" value="" size="40" aria-required="true" />
        <p class="description"><?php _e('This image will be the thumbnail shown on the category page.'); ?></p>
    </div>
<?php } 

add_action('created_category', 'save_category_metadata', 10, 1);

function save_category_metadata($term_id)
{
    if (isset($_POST['image-url'])) 
        update_term_meta( $term_id, 'image-url', $_POST['image-url']);                  
}

É fácil chamar novos campos em temas:

<?php echo get_term_meta(get_query_var('cat'), 'image-url', true); ?>

Mais detalhes e exemplos: http://www.wphub.com/adding-metadata-taxonomy-terms/

Jay
fonte