Agregar atributos de página Metabox y plantillas de página a la página de edición de publicaciones?

14

( Nota de los moderadores: el título era originalmente "¿Cómo puedo agregar el selector" Atributos de página "y / o" Atributos de página> Plantilla "al editor POSTS)?

Actualmente, WP solo permite la asignación de una "plantilla" a las páginas (es decir post_type=='page'). También me gustaría extender esta funcionalidad a las publicaciones (es decir post_type=='post').

¿Cómo puedo agregar el metacuadro "Atributos de página" y, más específicamente, el selector de plantillas al editor de publicaciones?

Supongo que este es el código que colocaré en mi functions.phppara mi tema.

ACTUALIZACIÓN: He logrado agregar el menú desplegable de plantillas codificadas a mi editor de publicaciones, simplemente agregando el cuadro de selección html a mi cuadro de opciones meta personalizadas existente. Aquí está el código que estoy usando para eso ...

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

Y aquí está la función que escribe las opciones y el cuadro de selección de plantilla ...

//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
}

Y finalmente, el código para capturar los valores seleccionados al guardar ...

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;
}

Ahora, creo que todo lo que queda es (1) capturar la plantilla seleccionada y agregarla al meta de publicación para esta publicación y (2) modificar index.php y single.php para que use la plantilla elegida.

Scott B
fuente
@Scott B : Bueno, escribí toda mi respuesta antes de ver que tú también estabas trabajando en ello, y parece que lo has tomado en una dirección algo diferente a la de tu pregunta original sin opciones de seguimiento y sin índice. Espero que lo que hice todavía tenga valor para ti. Si no, quizás ayude a otros.
MikeSchinkel
Sí, has respondido la pregunta. Tomé un rumbo un poco diferente una vez que me di cuenta de que no necesitaba analizar el directorio y que podía codificar los valores de mis plantillas específicas. Es probable que aún necesite tomar prestado parte de su código para que WP pueda usar la plantilla asignada correcta para la publicación.
Scott B

Respuestas:

12

Odio ser el portador de malas noticias, pero WordPress codifica la funcionalidad de la plantilla de página para el tipo de publicación de "página" , al menos en v3.0 (eso podría cambiar en futuras versiones, pero no hay una iniciativa específica que conozca para cambiarlo) todavía. Así que esta es una de las pocas veces que estoy luchando para encontrar la manera de sortear algo sin hackear el núcleo).

La solución que se me ocurrió es básicamente copiar el código relevante del núcleo de WordPress y modificarlo según nuestras necesidades. Estos son los pasos (los números de línea son de v3.0.1):

  1. Copie la page_attributes_meta_box()función de la línea 535 de /wp-admin/includes/meta-boxes.phpy modifíquela según convenga.

  2. Codifique un add_meta_boxesgancho para agregar el metabox creado en el n. ° 1.

  3. Copie la get_page_templates()función de la línea 166 /wp-admin/includes/theme.php y modifíquela para adaptarla.

  4. Copie la page_template_dropdown()función de la línea 2550 /wp-admin/includes/template.phpy modifíquela según convenga.

  5. Agregue una plantilla de publicación a su tema.

  6. Codifique un save_postgancho para permitir el almacenamiento del nombre del archivo de plantilla de publicación al guardar.

  7. Codifique un single_templategancho para permitir la carga de la plantilla de publicación para las publicaciones asociadas.

Ahora con eso!


1. Copie la page_attributes_meta_box()función

Como primer paso, debe copiar la page_attributes_meta_box()función de la línea 535 /wp-admin/includes/meta-boxes.phpy he elegido cambiarle el nombre post_template_meta_box(). Como solo solicitó plantillas de página, omití el código para especificar una publicación principal y para especificar el orden que hace que el código sea mucho más simple. También elegí usar postmeta para esto en lugar de intentar reutilizar la page_templatepropiedad del objeto para evitar posibles incompatibilidades causadas por un acoplamiento involuntario. Así que aquí está el 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 un add_meta_boxesgancho

El siguiente paso es agregar el metabox usando el 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 la get_page_templates()función

Supuse que solo tendría sentido diferenciar entre las plantillas de página y la plantilla de publicación, por lo tanto, la necesidad de una get_post_templates()función basada en la get_page_templates()línea 166 de /wp-admin/includes/theme.php. Pero en lugar de usar el Template Name:marcador, qué plantillas de página usan esta función, usa un Post Template:marcador que puede ver a continuación.

También me filtrada a cabo la inspección de functions.php (no sé cómo get_page_templates()nunca ha funcionado correctamente sin eso, pero lo que sea!) Y lo único que queda es cambiar las referencias a la palabra pageque postpara facilitar la lectura de mantenimiento en el futuro:

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 la page_template_dropdown()función

Del mismo modo, copie page_template_dropdown()desde la línea 2550 de /wp-admin/includes/template.phppara crear post_template_dropdown()y simplemente cámbielo para llamar en su get_post_templates()lugar:

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. Agregar una plantilla de publicación

El siguiente paso es agregar una plantilla de publicación para probar. Usando el Post Template:marcador mencionado en el paso 3 copia single.phpde tu tema single-test.phpy agrega el siguiente encabezado de comentario ( asegúrate de modificar algo single-test.phppara que puedas decir que se está cargando en lugar de single.php) :

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

Una vez que haya realizado los pasos 1 al 5, puede ver su metabox "Publicar plantillas" en su página de editor de publicaciones:

Aspecto de Metabox de plantillas de publicación cuando se agrega a WordPress 3.0
(fuente: mikeschinkel.com )

6. Codifique un save_postgancho

Ahora que tiene el editor ajustado, debe guardar el nombre del archivo de plantilla de página en postmeta cuando el usuario hace clic en "Publicar". Aquí está el código para eso:

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 un single_templategancho

Y, por último, debe obtener WordPress para usar sus nuevas plantillas de publicación. Para ello, engancha single_templatey devuelve el nombre de la plantilla deseada para las publicaciones a las que se les ha asignado una:

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;
}

¡Y eso es todo!

TEN EN CUENTA que no tomé en cuenta solo los tipos de publicaciones personalizadaspost_type=='post' . En mi opinión, abordar los tipos de publicaciones personalizadas requeriría diferenciar entre los diferentes tipos de publicaciones y, aunque no es demasiado difícil, no lo intenté aquí.

MikeSchinkel
fuente
¡Excelente! Me fui a dormir con un código casi completo en mi editor con el mismo enfoque de copiar las funciones predeterminadas de WordPress (estaba completo, pero no lo publicaría ya que no hice la prueba). :)
sorich87
@ sorich87 - Ya sabes el viejo dicho, Duermes , pierdes !" Hablando en serio, sólo es broma. En realidad, solo hay una manera razonable de hacerlo funcionar, por lo que no es de extrañar que su código sea el mismo.
MikeSchinkel
Mike, sigues asombrado. Muchas gracias por tomarse el tiempo para resolver esto.
Scott B
@ sorich87 - Gracias por trabajar en ello. Realmente aprecio el esfuerzo.
Scott B
1
@ Scott B : No hay problema, me alegro de poder ayudar. Busco preguntas razonablemente genéricas que podrían ayudar a muchas personas y trato de responderlas no solo para la persona que hace la pregunta, sino también para aquellos que pueden venir después.
MikeSchinkel
0

Wordpress le permite agregar Meta a las Categorías usando un complemento:

Para hacer esto, debe agregar una de las diversas extensiones que agrega meta a las categorías (imitando qué páginas salen de la caja), Simple Term Meta hace el trabajo muy bien.

NB WordPress 3.x es necesario para ampliar las categorías.

Después de eso puedes usar:

  • add_term_meta
  • update_term_meta
  • get_term_meta

Use Functions.php para agregar métodos para hacer lo que quiera, por ejemplo

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']);                  
}

Llamar a nuevos campos en los temas es fácil:

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

Más detalles y ejemplos: http://www.wphub.com/adding-metadata-taxonomy-terms/

Arrendajo
fuente