lunes, 19 de agosto de 2013

8. La plantilla Index de su Tema de WordPress

(El artículo original y en inglés, fue publicado el 1 de noviembre de 2012)

ThemeShaper es el sitio del Equipo de Temas de Automattic, que, en junio de 2009, publicó una muy popular serie de 11 artículos de Ian Stewart, bajo el título: How To Create a WordPress Theme: The Ultimate WordPress Theme Tutorial (Como crear un Tema de WordPress: el tutorial definitivo).
El año pasado, reflotó y actualizó ese tutorial. Esta vez con 16 artículos a cargo de Michelle LangstonThe ThemeShaper WordPress Theme Tutorial: 2nd Edition (Tutorial de Temas de WordPress de ThemeShaper. Segunda edición).
Me propongo traducir libremente esas 16 entradas (además de la introducción) e ir publicándolas a medida que las tenga listas.
Al final de cada entrada va el listado con todas las entradas de este tutorial.


Index.php es la más crucial de las plantillas de un Tema de WordPress. No solo porque WordPress la necesita para usar en caso que no existan cualquiera de sus plantillas hermanas e hijas (como, archive.php o tag.php) sino porque el trabajo que hagamos aquí, definir correctamente esta plantilla, nos ayudará a pasar fácilmente por el resto de las plantillas (con la excepción de la tan temida plantilla de comentarios; que es dificultosa sin importar cómo se la encare).
Por favor, note: Esta lección asume que ya ha agregado los elementos html estructurales básicos a su archivo index.php, tal como tratamos en Plantillas y estructura de directorios de un Tema de WordPress. Si su archivo index.php está vacío, por favor, primero complete esa lección pendiente y luego vuelva a este punto.



Llamando al Header

Abra index.php. Ya agregamos algo de estructura html básica en Plantillas y estructura de directorios de un Tema de WordPress. Aquí está como se debería estar viendo el index.php al final de esa lección.

<div id="primary" class="content-area">
    <div id="content" class="site-content">
    </div><!-- #content .site-content -->
</div><!-- #primary .content-area -->

Pegue el siguiente código al principio del archivo, antes que cualquier otra cosa.

<?php
/**
 * The main template file.
 *
 * This is the most generic template file in a WordPress theme
 * and one of the two required files for a theme (the other being style.css).
 * It is used to display a page when nothing more specific matches a query.
 * E.g., it puts together the home page when no home.php file exists.
 * Learn more: http://codex.wordpress.org/Template_Hierarchy
 *
 * @package Shape
 * @since Shape 1.0
 */
 
get_header(); ?>

Es la habitual información del documento, seguida de un llamado a la función  get_header() al final. Esta función le dice a WordPress que incluya el archivo  header.php.

El Bucle (The Loop)

Aunque está incrustado en el medio de su plantilla, en un sentido metafórico,  index.php comienza y termina con el Bucle (The Loop). Sin él no se tiene nada. Así es como se ve:

<?php while ( have_posts() ) : the_post() ?>
<?php endwhile; ?>

Realmente simple. Y no solo aparentemente simple. Mientras tenga entradas en su base de datos, su Tema hará un bucle a través de ellas y, por cada una, hará algo. El truco está en definir correctamente ese "algo". Pero, hasta eso puede ser simple.
Pruebe este bucle para empezar y trabajaremos en la construcción de todo el resto. Coloque el siguiente código dentro de su div .site-content en index.php.

<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php the_content(); ?>
<?php endwhile; ?>

Aquí está como su div .site-content debería verse:

<div id="content" class="site-content" role="main">
<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
     <?php the_content(); ?>
<?php endwhile; ?>
</div><!-- #content .site-content -->

¿Qué se obtiene con este código? Todo el contenido de todas las entradas en una gran y aplastada pila. Pero podría ser diferente.

<?php while ( have_posts() ) : the_post() ?>
<div class="entry-summary">
     <?php the_excerpt(); ?>
</div><!-- .entry-summary -->
<?php endwhile; ?>

¿Ve lo que acabamos de hacer aquí? Ahora, tiene un bucle que lista los extractos de las entradas dentro de divs, cada uno con la clase .entry-summary. (Además, ahora puede ver qué hacen the_content() y the_excerpt()).

Básicamente, se hace un bucle (que comienza con while y termina con endwhile) y se colocan algunas cosas dentro de él — cosas que son etiquetas de plantilla de WordPress que obtienen información de las entradas por las que estamos pasando con el bucle, al igual que  bloginfo() obtenía la información de configuración de nuestro WordPress en la lección anterior.

Muy bien, vamos a hacer un bucle realmente impresionante. Comencemos con nuestra básica y aplastada pila. Pero nos aseguraremos que esté lista para la etiqueta More y la etiqueta Next Page. También lo ponderemos en su propio div y, con la clase de microformato “entry-content”, le permitiremos saber a las máquinas que se trata del contenido de una entrada de un blog. Finalmente, queremos mostrar extractos en las páginas de resultados de las búsquedas, y el contenido completo en todas las demás páginas. Aquí tiene cómo se ve. No hay necesidad de pegar nada aún, tan solo observe.

<?php if ( is_search() ) : // Only display Excerpts for Search ?>
<div class="entry-summary">
     <?php the_excerpt(); ?>
</div><!-- .entry-summary -->
<?php else : ?>
<div class="entry-content">
     <?php the_content( __( 'Continue reading <?span class="meta-nav">→<?/span>', 'shape' ) ); ?>
     <??php wp_link_pages( array( 'before' => '<?div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '<?/div>' ) ); ?>
<?/div><?!-- .entry-content -->
<??php endif; ?>

¿Qué pasa con el título de la entrada? Eso también es muy sencillo. Usaremos la etiqueta de plantilla the_title() para obtener el título de la entrada y para envolverlo en una etiqueta que lo vincule a the_permalink() (o sea, a un vínculo permanente hacia una entrada en particular). También le agregaremos un atributo título (title) y otro microformato (bookmark) que le dice a las máquinas (como Google) que eso es un vínculo permanente a la entrada de un blog. Aquí está como quedaría nuestro código hasta ahora, con el título agregado. Nuevamente, evite pegar nada por ahora.

<header class="entry-header">
     <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', '_s' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
</header><!-- .entry-header -->
 
<?php if ( is_search() ) : // Only display Excerpts for Search ?>
<div class="entry-summary">
     <?php the_excerpt(); ?>
</div><!-- .entry-summary -->
<?php else : ?>
<div class="entry-content">
     <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?>
     <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?>
</div><!-- .entry-content -->
<?php endif; ?>

Ahora, vamos por todos los bits de información extra que acompañan a cualquier entrada de un blog: quién lo escribió, el momento en que se publicó, la categoría a la que pertenece, sus etiquetas, vínculos a comentarios. Me gusta dividir esto en dos secciones: la meta información (fecha y autor de la entrada) que la coloco antes del contenido de la entrada, y la información utilitaria (categorías, etiquetas y vínculos de comentarios) que la coloco después del contenido. También vamos a poner la entrada en su propio elemento article contenedor con el título.

Echemos un vistazo a todo el bucle completo. He insertado algunos comentarios php para que le sirvan como guía. Aún no hay necesidad de pegar nada (lo haremos muy pronto, lo prometo). Tan solo mire y aprenda.

<?php /* The Loop — with comments! */ ?>
<?php while ( have_posts() ) : the_post() ?>
<?php /* Create an HTML5 article section with a unique ID thanks to the_ID() and semantic classes with post_class() */ ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
     <header class="entry-header">
          <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', '_s' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
 
          <?php // if ( 'post' == get_post_type() ) : // Only display post date and author if this is a Post, not a Page. ?>
          <div class="entry-meta">
               <?php shape_posted_on(); ?>
          </div><!-- .entry-meta -->
          <?php endif; ?>
     </header><!-- .entry-header -->
 
     <?php if ( is_search() ) : // Only display Excerpts on Search results pages ?>
     <div class="entry-summary">
          <?php the_excerpt(); ?>
     </div><!-- .entry-summary -->
     <?php else : ?>
     <div class="entry-content">
          <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?>
          <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?>
     </div><!-- .entry-content -->
     <?php endif; ?>
 
<?php /* Show the post's tags, categories, and a comment link. */ ?>
     <footer class="entry-meta">
          <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for Pages in Search results ?>
          <?php
               /* translators: used between list items, there is a space after the comma */
               $categories_list = get_the_category_list( __( ', ', 'shape' ) );
               if ( $categories_list && shape_categorized_blog() ) :
          ?>
          <span class="cat-links">
               <?php printf( __( 'Posted in %1$s', 'shape' ), $categories_list ); ?>
          </span>
          <?php endif; // End if categories ?>
 
          <?php
               /* translators: used between list items, there is a space after the comma */
               $tags_list = get_the_tag_list( '', __( ', ', 'shape' ) );
               if ( $tags_list ) :
          ?>
               <span class="sep"> | </span>
               <span class="tag-links">
                    <?php printf( __( 'Tagged %1$s', 'shape' ), $tags_list ); ?>
               </span>
               <?php endif; // End if $tags_list ?>
          <?php endif; // End if 'post' == get_post_type() ?>
 
          <?php if ( ! post_password_required() && ( comments_open() || '0' != get_comments_number() ) ) : ?>
          <span class="sep"> | </span>
          <span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'shape' ), __( '1 Comment', 'shape' ), __( '% Comments', 'shape' ) ); ?></span>
          <?php endif; ?>
 
          <?php edit_post_link( __( 'Edit', 'shape' ), '<span class="sep"> |   </span><span class="edit-link">', '</span>' ); ?>
     </footer><!-- .entry-meta -->
<?php /* Close up the article and end the loop. */ ?>
</article><!-- #post-<?php the_ID(); ?> -->
<?php endwhile; ?>

Para mostrar la meta información (autor y fecha), llamaremos a una función de nombre shape_posted_on() (línea 10 del código anterior). Crearemos esta función un poquito más adelante.

Por ahora, hablemos algo más sobre la información utilitaria en el bloque de código (categorías y etiquetas), porque es... complicado. Creo que aquí verán los beneficios de obtener de una vez algo listo y pararse en los hombros de otros. Es complicado porque necesitamos tener en cuenta algunos escenarios diferentes: la existencia de una sola categoría y múltiples etiquetas; una categoría y ninguna etiqueta; múltiples categorías y múltiples etiquetas; o múltiples categorías y ninguna etiqueta. También tenemos que ocultar los vínculos a categorías y etiquetas de páginas en las páginas de resultados de búsquedas. Finalmente, queremos mostrar vínculos a comentarios solo si los comentarios están abiertos o si existe, por lo menos, un comentario. También queremos imprimir aquí un vínculo a nuestro permalink (vínculo permanente) para ser usado en los marcadores y, al final, el vínculo para edición de la entrada para los administradores del sitio.
Y eso resulta en... lo que parece un lío de declaraciones IF, como puede ver entre las líneas 26 a 57 del ejemplo de código precedente. Puede ser desalentador. El código está comentado, pero recuerde buscar los bloques de declaraciones IF y ELSEIF, y andará por el camino correcto.

Agregar funciones de metadatos

Ahora, vamos a crear la función shape_posted_on(). También vamos a agregar shape_categorized_blog() (vea la línea 32 del código anterior), una función que utilizamos para revisar si el blog tiene más de una categoría.

Ya que se trata de funciones que podremos reutilizar, las pondremos en template-tags.php. ¿Recuerda ese archivo (visto en Configuración de las funciones de su Tema)? Ábralo y agregue:

if ( ! function_exists( 'shape_posted_on' ) ) :
/**
 * Prints HTML with meta information for the current post-date/time and author.
 *
 * @since Shape 1.0
 */
function shape_posted_on() {
    printf( __( 'Posted on <a href="%1$s" title="%2$s" rel="bookmark"><time class="entry-date" datetime="%3$s" pubdate>%4$s</time></a><span class="byline"> by <span class="author vcard"><a class="url fn n" href="%5$s" title="%6$s" rel="author">%7$s</a></span></span>', 'shape' ),
        esc_url( get_permalink() ),
        esc_attr( get_the_time() ),
        esc_attr( get_the_date( 'c' ) ),
        esc_html( get_the_date() ),
        esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
        esc_attr( sprintf( __( 'View all posts by %s', 'shape' ), get_the_author() ) ),
        esc_html( get_the_author() )
    );
}
endif;
 
/**
 * Returns true if a blog has more than 1 category
 *
 * @since Shape 1.0
 */
function shape_categorized_blog() {
    if ( false === ( $all_the_cool_cats = get_transient( 'all_the_cool_cats' ) ) ) {
        // Create an array of all the categories that are attached to posts
        $all_the_cool_cats = get_categories( array(
            'hide_empty' => 1,
        ) );
 
        // Count the number of categories that are attached to the posts
        $all_the_cool_cats = count( $all_the_cool_cats );
 
        set_transient( 'all_the_cool_cats', $all_the_cool_cats );
    }
 
    if ( '1' != $all_the_cool_cats ) {
        // This blog has more than 1 category so shape_categorized_blog should return true
        return true;
    } else {
        // This blog has only 1 category so shape_categorized_blog should return false
        return false;
    }
}
 
/**
 * Flush out the transients used in shape_categorized_blog
 *
 * @since Shape 1.0
 */
function shape_category_transient_flusher() {
    // Like, beat it. Dig?
    delete_transient( 'all_the_cool_cats' );
}
add_action( 'edit_category', 'shape_category_transient_flusher' );
add_action( 'save_post', 'shape_category_transient_flusher' );

En shape_posted_on(), estamos utilizando un montón de etiquetas de plantilla para obtener la fecha, la hora, el autor, la url del archivo del autor y el vínculo permanente.

Con shape_categorized_blog(), estamos recuperando todas las categorías que tienen, al menos, una entrada, y almacenándolas en una variable temporal (conocida como “transitoria”) — $all_the_cool_cats — en formato de matriz (array). Si hay más de una categoría, éstas se mostrarán en los servicios de enlaces a entradas (ej. “Archivo de la categoría: Nombre de la Categoría”).

En la última función, shape_category_transient_flusher(), borramos la variable temporal $all_the_cool_cats siempre que 1) editemos una categoría; o 2) guardemos una entrada. ¿Por qué? Porque entonces es cuando puede agregar nuevas categorías. Al eliminar $all_the_cool_cats, se la fuerza a actualizarse permanentemente, de manera que se mantiene actualizada con la cantidad de categorías que tiene en su blog.

Simplificar nuestra plantilla Index

Ya tenemos el Bucle en su lugar. ¡Está tomando forma! Ahora, vamos a hacerlo aún mejor. Ya que vamos a utilizar en múltiples plantillas el código que está dentro del Bucle, ¿no estaría bueno si podemos escribir ese código solo una vez e invocarlo cada que lo necesitemos, en lugar de replicarlo en los archivos de plantillas?

¿No sería bueno, también,  si tuviéramos una forma decente de cambiar la apariencia de la entradas para cada Formato de Entrada con el que nuestro Tema sea compatible?

Afortunadamente para nosotros, existe una ingeniosa función de WordPressget_template_part(), que podemos utilizar para llevar a cabo todo lo anteriormente citado.

De acuerdo con el Codex de WordPress, get_template_part() le permite:
...cargar una parte de una plantilla en otra plantilla (que no sea header, sidebar, footer). Le facilita a un Tema reutilizar porciones de código y es, para los Temas Hijo (Child Theme), un camino sencillo para reemplazar secciones de su Tema Padre.
Ya que vamos a reutilizar el código dentro del Bucle, vamos a colocarlo en una "parte de plantilla" que podamos cargar en nuestro Tema en cualquier momento que lo necesitemos, a través de get_template_part().

Este es el motivo por el cual les dije que esperaran antes de pegar nada del código del Bucle en index.php. Pero ya es tiempo de pegatina. Abra content.php, y agregue el siguiente código (es el mismo que en el previo código de ejemplo, con algo de documentación agregada al inicio).

<?php
/**
 * @package Shape
 * @since Shape 1.0
 */
?>
 
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    <header class="entry-header">
        <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'shape' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
 
        <?php if ( 'post' == get_post_type() ) : ?>
        <div class="entry-meta">
            <?php shape_posted_on(); ?>
        </div><!-- .entry-meta -->
        <?php endif; ?>
    </header><!-- .entry-header -->
 
    <?php if ( is_search() ) : // Only display Excerpts for Search ?>
    <div class="entry-summary">
        <?php the_excerpt(); ?>
    </div><!-- .entry-summary -->
    <?php else : ?>
    <div class="entry-content">
        <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?>
        <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?>
    </div><!-- .entry-content -->
    <?php endif; ?>
 
    <footer class="entry-meta">
        <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for pages on Search ?>
            <?php
                /* translators: used between list items, there is a space after the comma */
                $categories_list = get_the_category_list( __( ', ', 'shape' ) );
                if ( $categories_list && shape_categorized_blog() ) :
            ?>
            <span class="cat-links">
                <?php printf( __( 'Posted in %1$s', 'shape' ), $categories_list ); ?>
            </span>
            <?php endif; // End if categories ?>
 
            <?php
                /* translators: used between list items, there is a space after the comma */
                $tags_list = get_the_tag_list( '', __( ', ', 'shape' ) );
                if ( $tags_list ) :
            ?>
            <span class="sep"> | &lt/span>
            <span class="tag-links">
                <?php printf( __( 'Tagged %1$s', 'shape' ), $tags_list ); ?>
            </span>
            <?php endif; // End if $tags_list ?>
        <?php endif; // End if 'post' == get_post_type() ?>
 
        <?php if ( ! post_password_required() && ( comments_open() || '0' != get_comments_number() ) ) : ?>
        <span class="sep"> | </span>
        <span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'shape' ), __( '1 Comment', 'shape' ), __( '% Comments', 'shape' ) ); ?></span>
        <?php endif; ?>
 
        <?php edit_post_link( __( 'Edit', 'shape' ), '<span class="sep"> | </span><span class="edit-link">', '</span>' ); ?>
    </footer><!-- .entry-meta -->
</article><!-- #post-<?php the_ID(); ?> -->

Ahora, regrese a index.php, y quite todo el código que está entre <div class="site-content" id="content"> y </div><!-- #content .site-content -->. Remplácelo con lo siguiente:

<?php if ( have_posts() ) : ?>
     <?php /* Start the Loop */ ?>
     <?php while ( have_posts() ) : the_post(); ?>
 
          <?php
          /* Include the Post-Format-specific template for the content.
          * If you want to overload this in a child theme then include a file
          * called content-___.php (where ___ is the Post Format name) and    that will be used instead.
          */
          get_template_part( 'content', get_post_format() );
          ?>
     <?php endwhile; ?>
<?php endif; ?>

¿Ve lo que estamos haciendo aquí? En español simple, significa: “Por defecto, rellene este Bucle con el código dentro de content.php. Pero, primero, verifique el Formato de Entrada para esta entrada. Busque entre los archivos del Tema una plantilla específica para ese Formato de Entrada, como, por ejemplo, content-aside.php, or content-quote.php. Si la encuentra, cargue esa plantilla para esta entrada. De lo contrario, cargue content.php.”

Y ahí lo tenemos. Una estructura clara para nuestro Bucle que podemos reutilizar en múltiples oportunidades. Además, ahora podemos crear diferentes diseños para nuestros Formatos de Entradas.

El Formato de Entrada "Aside" (Minientrada)

Previamente, hemos añadido soporte para el Formato de Entrada "Aside" (Minientrada). Así que vamos a hacer algo al respecto. Cómo se muestra cada formato depende de usted, pero las directrices en el Codex son un buen punto de partida.

De acuerdo con esas directrices, las entradas con el Formato de Entrada "Aside" (Minientrada) deberían ser cortas y suaves, y normalmente van formateadas sin título. Vamos a hacer eso. También vamos a ocultar el nombre del autor y las categorías y etiquetas.

Si vuelve a Plantillas y estructura de directorios de un Tema de WordPress, verá que allí creamos content-aside.php, una plantilla específica para entradas con el Formato de Entrada Aside (Minientrada). Abra ese archivo y pegue lo siguiente:

<?php
/**
 * The template for displaying posts in the Aside post format
 * @package Shape
 * @since Shape 1.0
 */
?>
 
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    <header class="entry-header">
        <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'shape' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
    </header><!-- .entry-header -->
 
    <?php if ( is_search() ) : // Only display Excerpts for Search ?>
    <div class="entry-summary">
        <?php the_excerpt(); ?>
    </div><!-- .entry-summary -->
    <?php else : ?>
    <div class="entry-content">
        <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?>
        <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?>
    </div><!-- .entry-content -->
    <?php endif; ?>
 
    <footer class="entry-meta">
        <a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'shape' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php echo get_the_date(); ?></a>
        <?php if ( ! post_password_required() && ( comments_open() || '0' != get_comments_number() ) ) : ?>
        <span class="sep"> | </span>
        <span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'shape' ), __( '1 Comment', 'shape' ), __( '% Comments', 'shape' ) ); ?></span>
        <?php endif; ?>
 
        <?php edit_post_link( __( 'Edit', 'shape' ), '<span class="sep"> | </span><span class="edit-link">', '</span>' ); ?>
    </footer><!-- .entry-meta -->
</article><!-- #post- -->

Verá que es prácticamente idéntico a content.php, menos el título, el nombre del autor, categorías y etiquetas. Y ahí lo tiene, ¡una plantilla específica para un Formato de Entrada!

Navegación

Ahora necesitamos una forma de navegar a través de las entradas — tanto en entradas individuales como en  páginas de archivo.

Para las páginas de archivo, lo haremos con dos Etiquetas de Entrada de WordPress: next_posts_link() y previous_posts_link(). Estas dos funciones... no hacen lo que ustedes piensan que hacen. Creo que el Codex de WordPress lo explica mejor:
next posts link
Esto crea un enlace a la entrada previa. Sí, dice “next posts” pero está nombrado así solo para confundirlo.
previous posts link
Esto crea un enlace a la entrada posterior. Sí, dice “previous posts”, pero está nombrado así solo para confundirlo.
Como todo en index.php, la navegación entre entradas necesita que se le de una planificación cuidadosa cuando estamos creándola, porque vamos a terminar usándola en casi todas las páginas de nuestro blog.

Me gusta tener los enlaces de navegación arriba y abajo del contenido de la entrada. Según como use este código en cada situación en particular, aunque podría no usarlo. No se preocupe, siempre podemos ocultarlo de esta manera:

.single #nav-above {
    display:none;
}

Este código CSS ocultará los enlaces de navegación de arriba ("above") del contenido en las entradas individuales.

Al igual que hicimos para el Bucle, vamos a colocar el código para nuestra navegación dentro de una función multipropósito que pueda producir la navegación tanto para las entradas individuales como para las páginas de archivo. Llamaremos a la función desde nuestras plantillas donde sea que querramos que se muestren los enlaces de navegación. De esta forma, nos evitamos la repetición innecesaria de código.

Regrese a inc/template-tags.php. Allí es donde vamos a colocar nuestra función de navegación. Agreguen lo siguiente, al final del archivo.

if ( ! function_exists( 'shape_content_nav' ) ):
/**
 * Display navigation to next/previous pages when applicable
 *
 * @since Shape 1.0
 */
function shape_content_nav( $nav_id ) {
    global $wp_query, $post;
 
    // Don't print empty markup on single pages if there's nowhere to navigate.
    if ( is_single() ) {
        $previous = ( is_attachment() ) ? get_post( $post->post_parent ) : get_adjacent_post( false, '', true );
        $next = get_adjacent_post( false, '', false );
 
        if ( ! $next && ! $previous )
            return;
    }
 
    // Don't print empty markup in archives if there's only one page.
    if ( $wp_query->max_num_pages < 2 && ( is_home() || is_archive() || is_search() ) )
        return;
 
    $nav_class = 'site-navigation paging-navigation';
    if ( is_single() )
        $nav_class = 'site-navigation post-navigation';
 
    ?>
    <nav role="navigation" id="<?php echo $nav_id; ?>" class="<?php echo $nav_class; ?>">
        <h1 class="assistive-text"><?php _e( 'Post navigation', 'shape' ); ?></h1>
 
    <?php if ( is_single() ) : // navigation links for single posts ?>
 
        <?php previous_post_link( '<div class="nav-previous">%link</div>', '<span class="meta-nav">' . _x( '←', 'Previous post link', 'shape' ) . '</span> %title' ); ?>
        <?php next_post_link( '<div class="nav-next">%link</div>', '%title <span class="meta-nav">' . _x( '→', 'Next post link', 'shape' ) . '</span>' ); ?>
 
    <?php elseif ( $wp_query->max_num_pages > 1 && ( is_home() || is_archive() || is_search() ) ) : // navigation links for home, archive, and search pages ?>
 
        <?php if ( get_next_posts_link() ) : ?>
        <div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">←</span> Older posts', 'shape' ) ); ?></div>
        <?php endif; ?>
 
        <?php if ( get_previous_posts_link() ) : ?>
        <div class="nav-next"><?php previous_posts_link( __( 'Newer posts ', 'shape' ) ); ?></div>
        <?php endif; ?>
 
    <?php endif; ?>
 
    </nav>
    <?php
}
endif; // shape_content_nav


Ahora vamos a llamar a esta función desde nuestra plantilla index. Vuelva a index.php y agregue lo siguiente, justo antes del Bucle.

<?php shape_content_nav( 'nav-above' ); ?>

Y justo después del Bucle, agregue el siguiente código:

<?php shape_content_nav( 'nav-below' ); ?>

Su archivo index.php debería verse así:

<?php
/**
* The main template file.
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
* E.g., it puts together the home page when no home.php file exists.
* Learn more: http://codex.wordpress.org/Template_Hierarchy
*
* @package Shape
* @since Shape 1.0
*/
 
get_header(); ?>
 
<div id="primary" class="content-area">
    <div id="content" class="site-content" role="main">
 
    <?php if ( have_posts() ) : ?>
 
        <?php shape_content_nav( 'nav-above' ); ?>
 
        <?php /* Start the Loop */ ?>
        <?php while ( have_posts() ) : the_post(); ?>
 
            <?php
                /* Include the Post-Format-specific template for the content.
                 * If you want to overload this in a child theme then include a file
                 * called content-___.php (where ___ is the Post Format name) and that will be used instead.
                 */
                get_template_part( 'content', get_post_format() );
            ?>
 
        <?php endwhile; ?>
 
        <?php shape_content_nav( 'nav-below' ); ?>
 
    <?php endif; ?>
 
    </div><!-- #content .site-content -->
</div><!-- #primary .content-area -->

Mire a shape_content_nav() en template-tags.php.

function shape_content_nav( $nav_id ) {

Puede ver que $nav_id es la variable que contiene el parámetro que le pasamos a la función cuando la llamamos en la plantilla index. $nav_id es igual a ‘nav-above’ y ‘nav-below’ para la navegación de arriba y de abajo, respectivamente. ¿Qué hace la función con $nav_id? Eche un vistazo a esta línea:

<nav role="navigation" id="<?php echo $nav_id; ?>" class="<?php echo $nav_class; ?>">

$nav_id se convierte en el nombre del selector ID del elemento nav. Esto le permite apuntar a este elemento en particular con CSS, de forma de ocultarlo o darle un estilo distinto.

Agregar el archivo de plantilla "no-results.php"

Si revisa index.php, podrá ver que, si existen entradas en la base de datos, el Bucle carga el archivo  content.php. Pero, ¿qué pasa si no existen entradas? Mostremos un mensaje para cuando no se puedan encontrar entradas. Del mismo modo que hicimos para el contenidos de la entrada y para el Formato de Entrada "Aside" (Minientrada), vamos a colocar un mensaje en archivo de plantilla. Abra no-results.php, y agregue lo siguiente:

<?php
/**
 * The template part for displaying a message that posts cannot be found.
 *
 * Learn more: http://codex.wordpress.org/Template_Hierarchy
 *
 * @package Shape
 * @since Shape 1.0
 */
?>
 
<article id="post-0" class="post no-results not-found">
    <header class="entry-header">
        <h1 class="entry-title"><?php _e( 'Nothing Found', 'shape' ); ?></h1>
    </header><!-- .entry-header -->
 
    <div class="entry-content">
        <?php if ( is_home() && current_user_can( 'publish_posts' ) ) : ?>
 
            <p><?php printf( __( 'Ready to publish your first post? <a href="%1$s">Get started here</a>.', 'shape' ), admin_url( 'post-new.php' ) ); ?>
<?php elseif ( is_search() ) : ?>
 
            <p><?php _e( 'Sorry, but nothing matched your search terms. Please try again with some different keywords.', 'shape' ); ?></p>
            <?php get_search_form(); ?>
 
        <?php else : ?>
 
            <p><?php _e( 'It seems we can’t find what you’re looking for. Perhaps searching can help.', 'shape' ); ?></p>
            <?php get_search_form(); ?>
 
        <?php endif; ?>
    </div><!-- .entry-content -->
</article><!-- #post-0 .post .no-results .not-found -->

No muy diferente a content.php y content-aside.php. Incluso tenemos un mensaje específico para mostrar cuando una búsqueda no obtenga ningún resultado (esto será útil durante la lección sobre search.php).
A continuación, tenemos que incluir no-results.php en index.php. Abra index.php y agregue lo que sigue, justo después de <?php shape_content_nav( 'nav-below' ); ?> y antes de <?php endif>.

<?php else : ?>
     <?php get_template_part( 'no-results', 'index' ); ?>

Llamada a la barra lateral y al pie

Una última cosa y terminamos con index.php. Al final del archivo, llamaremos a los archivos sidebar.php y footer.php con el siguiente código.

<?php get_sidebar(); ?>
<?php get_footer(); ?>

Aquí tienen cómo se debe ver el archivo index.php terminado.

<?php
/**
* The main template file.
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
* E.g., it puts together the home page when no home.php file exists.
* Learn more: http://codex.wordpress.org/Template_Hierarchy
*
* @package Shape
* @since Shape 1.0
*/
 
get_header(); ?>
 
<div id="primary" class="content-area">
    <div id="content" class="site-content" role="main">
 
    <?php if ( have_posts() ) : ?>
 
        <?php shape_content_nav( 'nav-above' ); ?>
 
        <?php /* Start the Loop */ ?>
        <?php while ( have_posts() ) : the_post(); ?>
 
            <?php
                /* Include the Post-Format-specific template for the content.
                 * If you want to overload this in a child theme then include a file
                 * called content-___.php (where ___ is the Post Format name) and that will be used instead.
                 */
                get_template_part( 'content', get_post_format() );
            ?>
 
        <?php endwhile; ?>
 
        
 
    <?php else : ?>
 
        <?php get_template_part( 'no-results', 'index' ); ?>
 
    <?php endif; ?>
 
    </div><!-- #content .site-content -->
</div><!-- #primary .content-area -->
 
<?php get_sidebar(); ?>
<?php get_footer(); ?>



Sumario de entradas

  1. Introducción.
  2. El desarrollo de su "sentido temático".
  3. Herramientas para el desarrollo de Temas de WordPress.
  4. Creación de una estructura html para su Tema de Wordpress.
  5. Plantillas y estructura de directorios de un Tema de WordPress.
  6. Configuración de las funciones de su Tema.
  7. Asegure su Tema de WordPress.
  8. La plantilla cabecera del tema de WordPress: header.php.
  9. La plantilla Index de su Tema de WordPress.
  10. Las plantillas Entrada Individual, Entrada de Adjuntos y error 404 del Tema de WordPress .
  11. La plantilla de comentarios de un Tema de WordPress.
  12. La plantilla de búsqueda (search) y la plantilla página (page) del Tema de WordPress.
  13. La plantilla Archivo .
  14. Las plantillas "sidebar" (barra lateral) y "footer" (pie de página) del Tema de WordPress.
  15. Como resetear y reconstruir los CSS de su Tema de WordPress y definir su diseño.
  16. Fondo y cabecera personalizados.
  17. Distribuir su Tema de WordPress.

No hay comentarios.:

Publicar un comentario

Lo que escriba a continuación será revisado antes de publicarse.
Gracias por tus comentarios.