Campo personalizado / meta preenchido pelo menu suspenso de postagens existentes?

11

(Minha primeira pergunta WP já feita! Seja gentil!)

Estou construindo um site composto principalmente de páginas (estáticas), usando o WP como CMS. Na parte inferior de várias páginas, aparecerão 1, 2 ou 3 "caixas promocionais" - basicamente imagens de botões com links para outras partes do site. Embora apenas três caixas promocionais apareçam em uma página, haverá ~ 30 diferentes para você escolher.

Quando meu cliente cria uma nova página, gostaria que ele pudesse escolher caixas promocionais de algo como uma lista suspensa de todas as possíveis caixas promocionais.

Parece-me que isso deve funcionar assim:

  • Crie um tipo de postagem personalizado chamado "caixa promocional". (Embora possa facilmente ser uma tag para postagens regulares.)
  • Use uma ferramenta como Modelo de campo personalizado para criar uma lista suspensa no editor de páginas, onde os valores das opções suspensas são gerados dinamicamente a partir da lista de todas as postagens existentes na caixa promocional. ( Esta é a parte que eu não sei fazer. )
  • Acesse os metadados resultantes (o número da postagem é realmente tudo o que eu preciso e posso obter todo o resto) no modelo da página.

Com base nas respostas a outras perguntas aqui, dei uma olhada inicial nos campos personalizados WPAlchemy MetaBox, Posts-2-Posts e SLT, mas confesso que a documentação de cada um deles é um pouco mais geek do que eu, então não me aprofundei muito profundamente.

Adendo? Uma das ferramentas acima é a solução certa para mim e só preciso descobrir isso? Estou faltando alguma coisa aqui?

Nic Warmenhoven
fonte
Uau, obrigado por todo o apoio! Espero não estar desvalorizando o tempo e a generosidade de MikeSchinkel, mas escolhi a resposta WPAlchemy como a resposta "oficial". Eu ainda sou novo o suficiente no PHP / Wordpress e ainda não estou super confortável com classes e ganchos e funções estáticas e coisas do tipo. Espero que um dia seja tão proficiente quanto vocês!
Nic Warmenhoven

Respostas:

7

Como autor do WPAlchemy , sou um pouco tendencioso, mas você basicamente tem um bom modelo de trabalho a seguir, dependendo do caminho que você escolher.

No entanto, se você estiver usando o WPAlchemy, basicamente faria algo como o seguinte (etapa 2):

//  functions.php

include_once 'WPAlchemy/MetaBox.php';

if (is_admin()) 
{
    // a custom style sheet if you want to do some fancy styling for your form
    wp_enqueue_style('custom_meta_css', TEMPLATEPATH . '/custom/meta.css');
}

// define the meta box
$custom_metabox = new WPAlchemy_MetaBox(array
(
    'id' => '_custom_meta',
    'title' => 'My Custom Meta',
    'template' => TEMPLATEPATH . '/custom/meta.php'
));

custom/meta.csspode conter estilos com os quais você pode estilizar seu formulário e custom/meta.phpé essencialmente um arquivo HTML com o conteúdo FORM da caixa meta; nesse caso, sua lista suspensa, para gerar sua lista suspensa, você faria uma consulta wp personalizada para obter todas as suas postagens personalizadas tipos. O WPAlchemy possui algumas funções auxiliares especiais para ajudar na criação dos elementos do formulário.

documentação adicional para ajudá-lo a trabalhar no modelo.

O principal objetivo do WPAlchemy era manter o controle nas mãos do desenvolvedor, desde o estilo (aparência + sensação) até a definição do conteúdo da meta box.

E eu e outros sempre estamos dispostos a ajudar aqueles que comentam e fazem perguntas.

farinspace
fonte
1
Boa resposta, mas posso sugerir a conexão desse pedido de folha de estilo extra especificamente à tela de pós-edição. Mesmo também pode ser dito para a criação METABOX, que, idealmente, deve ser viciado em do_meta_boxescom alguma lógica condicional ou, alternativamente, para add_meta_boxes_{%TYPE%}..
t31os
14

Hehe, você é um novato! Vamos rasgar você em pedaços ...!

j / k :) Oferecemos boas-vindas a todos os novatos aqui, prazer em tê-lo.

Portanto, é a terceira vez que ouvi esse requisito, duas vezes de clientes e não novamente de você (e de seu cliente.) Isso me diz que é uma necessidade razoavelmente comum.

Metabox personalizada do WordPress, mostrando três (3) listas suspensas

Gostei da sua análise, então decidi codificar uma classe para abordar seu segundo ponto. Liguei LittlePromoBoxesporque nunca consigo tirar essa música da minha cabeça, graças a eles . Basicamente, uso a classe para encapsular para evitar possíveis conflitos de nomes com as funções que eu precisaria escrever.

Você pode colocar essa classe no functions.phparquivo do seu tema ou no arquivo .PHP de um plug-in que possa estar escrevendo (mas não se preocupe, parece muito mais complexo do que é).

A primeira função on_load()é uma função estática que eu chamo no final da declaração de classe para inicializar os três (3) ganchos necessários (as funções estáticas da fyi são essencialmente funções relacionadas à classe , não à instância) :

  1. O initgancho para registrar o promo-boxtipo de postagem,

  2. O add_meta_boxes_postgancho para permitir que você defina o metabox e

  3. O wp_insert_post_datagancho para permitir que você capture as caixas promocionais selecionadas e salve no banco de dados.

Cada um desses ganchos faz referência a outra função estática da classe (essas eram as funções que eu estava encapsulando ao criar a classe).

Vou pular a descrição da action_init()função e minha make_labels()função auxiliar, assumindo que você saiba como registrar um tipo de postagem com base na sua pergunta.

A action_add_meta_boxes_post()função registra a metabox usando a função principal do WordPress add_meta_box()e eu comentei seus parâmetros para explicar por que passei no que passei para cada um. A função de retorno de chamada the_little_promo_boxes_metabox()é obviamente outra função estática da classe e é o que realmente exibe o conteúdo no metabox. Ele usa principalmente a função principal do WordPress wp_dropdown_pages()para exibir uma lista de caixas promocionais (observe que ele exibirá outros tipos de postagem além da 'página', mas apenas se eles estiverem marcados como estando 'hierarchical'=>trueem seu registro de tipo de postagem. Por que apenas hierárquico? Porque é dessa maneira que eles escreveu, é por isso! :)

Como mostramos três (3) listas suspensas, precisamos fornecer a cada um um ID exclusivo no HTML ( "promo_box_{$i}"), mas o mesmo nome entre colchetes ( 'promo_boxes[]'), para que o PHP os colete em uma matriz dentro da $_POSTvariável (que o WordPress acessa para nós; você verá como em um minuto) . E é claro que precisamos definir o valor selecionado ( (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])) se um dos valores já tiver sido selecionado anteriormente.

Também usei a função principal do WordPress get_post_type_object()para mostrar como obter os rótulos de um tipo de postagem, e também usando a função principal do WordPress get_post_meta()para recuperar uma matriz de IDs de caixas promocionais usando a chave de campo personalizada '_promo_boxes', que mostrarei que você tem para salvar em seguida (observe que usei um sublinhado anterior no nome '_promo_boxes'que faz com que o WordPress oculte da interface do usuário do campo personalizado padrão quando o usuário estiver editando a postagem.) .

A última função a ser descrita antes de você ver o código é o filter_wp_insert_post_data()que recebe os dados de postagem existentes no primeiro parâmetro ( $data) e o conteúdo da $_POSTmatriz, graças ao WordPress como o segundo parâmetro ( $postarr). Dentro dessa função, chamamos a função principal do WordPress update_post_meta()e extraímos o array das caixas promocionais ( $postarr['promo_boxes']) para salvar no valor do campo personalizado da chave '_promo_boxes'da postagem especificada pelo $_POSTarray (por exemplo $postarr['ID']).

Dito isto, aqui está o código para a LittlePromoBoxesclasse:

class LittlePromoBoxes {
  static function on_load() {
    add_action('init',array(__CLASS__,'action_init'));
    add_action('add_meta_boxes_post',array(__CLASS__,'action_add_meta_boxes_post'));
    add_filter('wp_insert_post_data',array(__CLASS__,'filter_wp_insert_post_data'),10,2);
  }
  static function action_init() {
    register_post_type('promo-box',array(
      'labels'          => self::make_labels('Promo Box','Promo Boxes'),
      'public_queryable'=> false,
      'hierarchical'    => true,  // IMPORTANT!!! wp_dropdown_pages() requires 'hierarchical'=>true
      'show_ui'         => true,
      'query_var'       => false,
      'supports'        => array('title','editor','thumbnail','custom-fields'),
      'show_in_nav_menus'=>true,
      'exclude_from_search'=>true,
    ));
  }
  static function make_labels($singular,$plural=false,$args=array()) {
    if ($plural===false)
      $plural = $singular . 's';
    elseif ($plural===true)
      $plural = $singular;
    $defaults = array(
      'name'              =>_x($plural,'post type general name'),
      'singular_name'      =>_x($singular,'post type singular name'),
      'add_new'            =>_x('Add New',$singular),
      'add_new_item'      =>__("Add New $singular"),
      'edit_item'          =>__("Edit $singular"),
      'new_item'          =>__("New $singular"),
      'view_item'          =>__("View $singular"),
      'search_items'      =>__("Search $plural"),
      'not_found'          =>__("No $plural Found"),
      'not_found_in_trash'=>__("No $plural Found in Trash"),
      'parent_item_colon' =>'',
    );
    return wp_parse_args($args,$defaults);
  }
  static function action_add_meta_boxes_post($post) {
    add_meta_box(
      'little-promo-boxes',   // Metabox Name, used as the "id" for a wrapping div
      'Little Promo Boxes',   // Metabox Title, visible to the user
      array(__CLASS__,'the_little_promo_boxes_metabox'), // Callback function
      'post',                 // Add to the Edit screen for Post Types of 'post'  
      'side',                 // Show it in the sidebar (if center then it would be 'normal'
      'low'                   // Show it below metaboxes that specify 'high'
    );
  }
  static function the_little_promo_boxes_metabox($post) {
    $pto = get_post_type_object('promo-box');
    $default_options = array(
      'post_type' => 'promo-box',
      'show_option_none' => "Select a {$pto->labels->singular_name}",
    );
    $promo_boxes = get_post_meta($post->ID,'_promo_boxes',true);
    for($i=0; $i<=2; $i++) {
      wp_dropdown_pages(array_merge($default_options,array(
        'id'       => "promo_box_{$i}",
        'name'     => 'promo_boxes[]',
        'selected' => (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i]),
      )));
    }
  }
  static function filter_wp_insert_post_data($data, $postarr) {
    update_post_meta($postarr['ID'],'_promo_boxes',$postarr['promo_boxes']);
    return $data;
  }
  static function get_promo_boxes($post=false) {
    static $promo_boxes=array();
    if (!$post)
      $post = $GLOBALS['post'];
    if (!isset($promo_boxes[$post->ID])) {
      $promo_boxes[$post->ID] = get_post_meta($post->ID,'_promo_boxes',true);
      $index = 0;
      foreach($promo_boxes[$post->ID] as $promo_box_id) {
        $promo_boxes[$post->ID][$index++] = (is_numeric($promo_box_id) ? get_post($promo_box_id) : false);
      }
    }
    return $promo_boxes[$post->ID];
  }
  static function get_promo_box($number,$post=false) {
    $promo_boxes = self::get_promo_boxes($post);
    return $promo_boxes[$number-1];
  }
}
LittlePromoBoxes::on_load();

Ainda existem duas (2) funções estáticas ainda não mencionadas: get_promo_boxes()e get_promo_box(); essas são funções auxiliares para ajudá-lo a recuperar as postagens post_type='promo-box'pelos seus números ordinais 1..3. Mas para torná-los mais WordPress, como aqui estão duas funções de wrapper para adicionar ao functions.phparquivo do seu tema (observe que você pode passar uma postagem como um parâmetro, mas não é necessário, a menos que esteja usando uma postagem diferente da do The Loop ) :

function get_little_promo_boxes($post=false) {
  return LittlePromoBoxes::get_promo_boxes($post);
}
function get_little_promo_box($number,$post=false) {
  return LittlePromoBoxes::get_promo_box($number,$post);
}

Agora você pode chamar uma ou ambas as funções no seu single.phparquivo de tema com um código que se parece com isso (esse código pode ter sido escrito em um loop, mas a maioria dos temáticos do WordPress parece gostar de duplicar o código para que possa lê-lo em vez de eliminar a redundância Então, quando em Roma ...):

<?php
  $promo_boxes = get_little_promo_boxes();
  if (isset($promo_boxes[1]))
    echo '<div id="promo-box1" class="promo-box">' . get_the_title($promo_boxes[1]->ID) . '</div>';
  if (isset($promo_boxes[2]))
    echo '<div id="promo-box2" class="promo-box">' . get_the_title($promo_boxes[2]->ID) . '</div>';
  if (isset($promo_boxes[3]))
    echo '<div id="promo-box3" class="promo-box">' . get_the_title($promo_boxes[3]->ID) . '</div>';
?>
MikeSchinkel
fonte
1
Você nunca deixa de me surpreender com suas respostas, o esforço que você faz para criar o código e explicar cada passo .. incrível! .. (sua menção de caixinhas também me faz pensar em uma das minhas séries de TV favoritas) ..
T31os
1
@ t31os - Obrigado! Quando começo a responder, simplesmente não consigo me conter. Obsessivo / compulsivo, eu acho. Mas pelo menos estou fazendo bom uso!
MikeSchinkel
@toscho - Obrigado. Sim, raramente acrescento humor que, quando se trata de mim, não consigo resistir. :-)
MikeSchinkel