Está en la página 1de 129

Taller para aprender a crear Themes WordPress desde cero

En 20 clases te explicamos la base para poder explotar todas las capacidades de esta potente y popular plataforma para gestionar contenidos.

2013 - Summarg.com

Introduccin
Este taller pretende introducir a la creacin de themes WordPress a aquellos con poca experiencia en el tema, por ende utilizaremos un nivel bsico en lo referente al tema. Apuntamos a que el lector aprenda a instalar un servidor local y pasar un diseo de PSD (Photoshop) a theme WordPress compuesto por diversos formatos de archivos (PHP, JS, CSS, imgenes, etc.). Para modificaciones de nivel medio y superior, pueden chequear nuestra seccin de WordPress que contina en constante actualizacin. Existen varios tutoriales en la red que ofrecen crear themes en pocos pasos, en 15 minutos o sin esfuerzo. Nosotros elaboramos un temario que consiste en varias clases puesto que nuestra intencin es que el lector aprenda a crear los themes entendiendo cada paso del proceso para poder tener la libertad de iniciarse luego en temas mas complejos y para lograr resultados cada vez mas interesantes. Las siguientes herramientas sern necesarias para poder seguir el tutorial: Notepad++ (gratuito) u otro editor de cdigo como Dreamweaver. Photoshop u otro editor de imgenes. XAMPP (gratuito) servidor local. FileZilla (opcional gratuito) o cualquier aplicacin FTP para subir tu trabajo a un servidor remoto. JS Screen Ruler (opcional gratuito) regla para tu pantalla, ayuda a ajustar detalles. Abarcaremos todos los temas listados de a uno por clase, insertando los enlaces en cada entrega semanal. El temario est sujeto a cambios segn lo veamos conveniente.

Indice de clases
Clase 1: Introduccin: Instalar WordPress en un servidor local ------------- Pag 5 XAMPP Generar una base de datos desde PhpMyAdmin Contenido de pruebas para la plataforma Clase 2: Cmo encarar el diseo a partir de un archivo PSD ----------------- Pag 8 Presentamos nuestra plantilla. Introduccin a las partes de un theme. Clase 3: Comenzamos a maquetar! --------------------------------------------------- Pag 11 Comenzamos a maquetar el index.php Funciones bsicas de header.php El archivo de estilos CSS Clase 4: El bucle y jerarquas de templates ----------------------------------------- Pag 21 El bucle Funcionamiento de la jerarqua de templates El bucle en los templates Clase 5: El bucle avanzado: Query_posts ------------------------------------------- Pag 25 Mltiples bucles en la misma pgina Uso bsico de the_post_thumbnail Clase 6: El archivo header.php y los mens en WordPress ------------------- Pag 29 Funcin de wp_head() Introduccin a condicionales de template Aplicaciones de bloginfo Mens con wp_nav_menu Clase 7: Implementar Nivo-slider sin plugins --------------------------------------- Pag 36 Trabajar con jQuery Insertar Nivo-Slider y adaptarlo al theme Clase 8: Sidebar y widgets ---------------------------------------------------------------- Pag 40 Qu son y cmo funcionan los widgets? Aadir mas sidebars Clase Anexo: Aadir una sidebar horizontal -------------------------------- Pag 45 Clase 9: El archivo footer.php ------------------------------------------------------------ Pag 48 Funcin y usos frecuentes Aadir rea de widgets Aadir men secundario y link al inicio

Clase 10: La plantilla de entrada y de comentarios ------------------------------- Pag 54 Single.php, layout y contenidos Los comentarios Clase 11: La plantilla de pgina ---------------------------------------------------------- Pag 64 Pginas personalizadas Pginas y subpginas Plantilla de pginas con query_posts Clase 12: archive.php y plantillas por categora, fecha, autor, taxonoma, etiqueta ---------------------------------------------------------------------------------------------- Pag 72 Extra: Mostrar favicon y tags para Facebook Template Conditionals: Categoras por id Template Conditionals: Autor, Etiquetas Clase 13: Pgina de bsquedas: search.php e integracin con Google CSE ------------------------------------------------------------------------------------------------------- Pag 80 Search.php y personalizacin de la plantilla Incorporar bsquedas con Google CSE Clase 14: Paginacin, breadcrumbs y pgina de error 404.php -------------- Pag 85 Snippets para paginar y para colocar breadcrumbs sin usar plugin Clase 15: Framework para opciones administrativas e insercin de anuncios ------------------------------------------------------------------------------------------------------- Pag 90 Insercin de anuncios Insercin de campos de texto Clase 16: Custom Post Types: Portfolio y plantilla single-cpt.php --------- Pag 97 Metabox: Los custom fields de forma fcil La plantilla single-cpt.php Clase 17: Custom Post Types: Portfolio y plantilla de taxonoma ---------- Pag 108 Plantilla de Taxonoma Pgina personalizada para el portfolio con jQuery Isotope Clase 18: Custom Post Types: Formulario de bsqueda ---------------------- Pag 116 Clase 19: Plugins y snippets recomendados -------------------------------------- Pag 121 Clase 20: Conclusiones y descarga del taller completo ----------------------- Pag 129
4

Clase 1: Instalar WordPress en XAMPP, un servidor local


WordPress es un CMS que necesita de un servidor Apache y una base de datos MySQL para funcionar. Para aprender a construir themes WordPress servir mucho poder instalar un servidor en nuestra propia PC, ya que nos ahorraremos el tiempo que demora en subir cada archivo modificado a un hosting y podremos llevar nuestro WordPress a todas partes sin necesidad de conexin a Internet.

Instalador de XAMPP
Con esta finalidad instalaremos XAMPP, un servidor disponible para varios sistemas operativos y cuya instalacin es muy sencilla. 1. Descargamos la versin de XAMPP que corresponda a nuestro sistema operativo desde aqu: http://sourceforge.net/projects/xampp/files/. El primer link que ofrecen es el del ltimo instalador para Windows disponible. 2. Lo ejecutamos y corremos la instalacin. Al finalizar, corremos la aplicacin y nos aseguramos de que estn corriendo los servicios Apache y MySQL. Ingresamos a http://localhost/ en nuestro navegador.

Es necesario saber que XAMPP es un servidor pensado en desarrolladores y no es recomendable para produccin (es decir, no se recomienda utilizar para abrir un website al pblico desde nuestra computadora). 3. phpMyAdmin es una aplicacin que nos permite gestionar todo lo referente a nuestras bases de datos, es una de las mas populares y gran parte de los hostings generalmente la ofrecen en sus paneles, as que es buena idea familiarizarse con la misma. Primero cambiaremos la contrasea, por defecto el campo viene vaco. Abrimos con nuestro Notepad++ el archivo c:/xampp/ phpmyadmin/config.inc.php, colocamos un usuario, su contrasea y cambiamos el valor de AllowNoPassword a false. $cfg[Servers][$i][user] = root; $cfg[Servers][$i][password] = ****; $cfg[Servers][$i][AllowNoPassword] = false; Ahora ingresamos a http://localhost/phpmyadmin y nos preparamos para crear una base de datos. Le asignaremos un nombre y cambiamos el cotejamiento de la base de datos a utf8_unicode_ci (es el ltimo select de la lista).

4. Nuestra base de datos ser wordpress, el usuario root y la contrasea la que hayamos definido en el config.inc.php arriba mencionado. Con esto completado ya podemos descargar la ltima versin de WordPress desde el sitio oficial y descomprimirlo dentro del directorio c:/xampp/ htdocs/. Abrimos el archivo wp-config-sample.php y editamos los siguientes datos. /** El nombre de tu base de datos de WordPress */ define(DB_NAME, wordpress); /** Tu nombre de usuario de MySQL */ define(DB_USER, root); /** Tu contrasea de MySQL */ define(DB_PASSWORD, tucontrasea); Guardamos el archivo con el nombre wp-config.php e ingresamos a http://localhost en nuestro navegador, nos llevar directo a la pantalla de instalacin de WordPress, en donde completamos

con los datos requeridos y ya estaremos listos.

5. Para completar nuestra clase de hoy cargaremos algn contenido de pruebas en nuestro WordPress, de modo de que tengamos algunas entradas, categoras y pginas con diferentes formatos de texto para visualizar cuando trabajemos cada plantilla. En esta nota ya habamos hablado de este recurso que pueden descargar directamente de aqu https://wpcom-themes.svn.automattic. com/demo/test-data.2011-01-17.xml En nuestro panel de administrador nos dirigimos a herramientas > importar > wordpress. Subimos el archivo y aceptamos. Con esto ya tendremos nuestro WordPress instalado en un servidor local y podremos empezar a trabajar en l en nuestra prxima clase.

Activar permalinks en XAMPP

La activacin de los permalinks de WordPress en nuestro servidor local XAMPP, WAMPP o AppServ puede resultar fundamental para trabajar con comodidad. Por lo general bastar con activar los Permalinks desde Ajustes > Enlaces permanentes y crear el .htaccess con el contenido que WordPress nos facilita. En algunos casos el mdulo rewrite no est activado por lo que tendremos que buscar el archivo httpd.conf dentro de apache/conf/. La carpeta apache puede llamarse apache2 dependiendo del software que utilicemos. Utilizamos un editor como Notepad++ y buscamos la siguiente lnea: #LoadModule rewrite_module modules/mod_rewrite.so Removemos el signo #. Luego buscamos las siguientes lneas: AllowOverride All## Controls who can get stuff from this server.#Order allow,denyAllow from all Y nos aseguramos de que AllowOverride All no tenga numeral. Guardamos y reiniciamos XAMPP.

Clase 2: Cmo encarar el diseo a partir de un archivo PSD


Bienvenidos a la segunda clase de Taller para crear un theme WordPress desde cero. En esta clase veremos como tomar un template en formato PSD (Adobe Photoshop) y convertirlo en un theme WordPress. Utilizaremos un template que hemos creado especialmente para este taller, lo bautizamos ThemeTaller. Est dividido en capas y agrupadas por secciones con un nombre descriptivo, pueden descargarlo y modificarlo libremente. Este template estar sujeto a modificaciones a lo largo del taller segn lo veamos conveniente. Les mostramos y entregamos el home de nuestro diseo. Descargar ThemeTaller: ThemeTaller

El set de conos sociales es Socialis21 y pueden encontrar el link de descarga aqu: Socialis21 En el pie de pgina pueden encontrar la paleta de colores utilizada para el theme y la compartimos para que puedan crear nuevas secciones dentro de la plantilla haciendo uso de la misma. Antes de empezar a maquetar conozcamos un poco lo que vamos a hacer. Los themes WordPress utilizan varios archivos a la vez para formar una pgina, que son llamados por funciones especficas de la plataforma para facilitar las cosas. Son similares a la funcin include de PHP y nos evitan tener que escribir la misma porcin de cdigo en varias plantillas. Por ejemplo, la seccin del encabezado del sitio siempre es igual, llevar un logo y una botonera que no deseamos que cambie. En un sitio construido ntegramente en HTML deberamos copiar este cdigo en cada una de las pginas. Pero en WordPress bastar con escribir todo el cdigo del encabezado dentro de header.php y luego solicitar el encabezado en cada seccin que lo necesite-

mos. Lo mismo cuenta para la barra lateral (sidebar.php) y el pi de pgina (footer.php). De ese modo cuando se lista el index de un sitio WordPress, ste estar compuesto de los archivos header.php, index.php, sidebar.php y footer.php. Para el caso de listar una pgina los archivos sern: header.php, page.php, sidebar.php y footer.php. Qu cambi? El inicio utiliza index. php para mostrar su contenido principal y una pgina utiliza el archivo page.php. Para solicitar desde el index.php los archivos en cuestin utilizaremos las funciones: get_header(); get_sidebar(); get_footer(); Entonces dividiremos el home (index.php) en 4 archivos que los marcamos a la derecha en la siguiente imagen (en el zip de descarga del theme encontrarn la imagen en tamao grande).

A la izquierda indicamos los elementos que consideramos necesario nombrar, con sus respectivos atributos class e id. De este modo el archivo header.php contendr, entre cosas, el elemento #header, que dentro de s contendr el un #menu-top, el #logo y el #menu. El contenido de la pgina (el fondo blanco con bordes redondeados) se llamar #content y el ancho del diseo ser fijo (960px). Todos los colores y bordes pueden definirse directamente desde el CSS, aunque si quieren ser fieles al diseo slo debern recortar un rectngulo pequeo con el fondo de la barra del men y el fondo gris de los productos destacados:

Para recortar las partes del theme en Photoshop, debern utilizar la herramienta mscara y seleccionar la seccin. En nuestro caso seleccionamos el logo. Luego seleccionan image > crop y guardan el resultado utilizando la opcin save for web & devices (guardar optimizado para la web) como logo.png. Tambin necesitarn repetir el proceso con los conos sociales.

10 La clase que viene comenzamos a maquetar esta pgina. Descarguen el archivo PSD y empiecen a ver como est compuesto.

Clase 3: Comenzamos a maquetar!


En la clase anterior estuvimos observando como se compone cada plantilla de WordPress, as que en vez de maquetar nuestra pgina de inicio en una sola pgina como si fuera un HTML comn, arrancaremos utilizando 4 archivos PHP y la plantilla de estilos CSS por separado. Dentro de nuestro directorio /wp-content/themes/, creamos un directorio llamado /themetaller/. Dentro de /themetaller/ colocaremos un subdirectorio /scripts/, que en principio estar vaco, y otro llamado /images/ en donde colocamos las imgenes recortadas en la clase anterior.

11

Creamos los siguientes archivos en nuestro directorio /themetaller/: index.php, footer.php, header. php, sidebar.php y style.css.

Y respetando la divisin de establecimos la clase pasada, comenzamos a crear el cdigo del header.php. Vamos a agregar en el encabezado, entre etiquetas <head> el siguiente cdigo: <!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http:// www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd> <html xmlns=http://www.w3.org/1999/xhtml <?php language_attributes(); ?>> <head profile=http://gmpg.org/xfn/11>

<meta http-equiv=Content-Type content=<?php bloginfo(html_type); ?>; charset=<?php bloginfo(charset); ?> /> <title> <?php if ( is_home() ) { ?><?php bloginfo(name); ?> | <?php bloginfo(description); ?><?php } ?> <?php if ( is_author() ) { ?><?php bloginfo(name); ?> | Archivo por autor<?php } ?> <?php if ( is_single() ) { ?><?php wp_title(); ?> | <?php wp_title(); ?><?php } ?> <?php if ( is_page() ) { ?><?php bloginfo(name); ?> | <?php wp_title(); ?><?php } ?> <?php if ( is_category() ) { ?><?php bloginfo(name); ?> | Archivo por Categoria | <?php single_cat_title(); ?><?php } ?> <?php if ( is_month() ) { ?><?php bloginfo(name); ?> | Archivo por Mes | <?php the_time(F); ?><?php } ?> <?php if ( is_search() ) { ?><?php bloginfo(name); ?> | Resultados<?php } ?> <?php if (function_exists(is_tag)) { if ( is_tag() ) { ?><?php bloginfo(name); ?> | Archivo por Tag | <?php single_tag_title(, true); } } ?> </title> <?php wp_head(); ?> <link rel=stylesheet type=text/css href=<?php bloginfo(stylesheet_ url); ?> media=screen /> <link rel=alternate type=application/rss+xml title=RSS 2.0 href=<?php bloginfo(rss2_url); ?> /> <link rel=pingback href=<?php bloginfo(pingback_url); ?> /> </head> El cdigo para el encabezado contiene informacin sobre el DOCTYPE, HTML, los meta, el charset, se vincula la plantilla de estilos, se indican los links de los feeds y del pingback, se colocan varios condicionales para el title (dependiendo de la seccin que se visualiza, mostrar un ttulo diferente) y finalmente la funcin wp_head(), que es la funcin que utiliza la plataforma para cargar scripts desde plugins y otra informacin adicional. Ahora si, maquetamos lo que vimos en la imagen de la clase pasada:

12

El cdigo HTML ser el siguiente: <body> <div id=content-wrapper> <div id=header> <div id=logo> <img src=http://localhost/wp-content/themes/themetaller/images/logo.png /> </div><!-- end of logo --> <ul id=menu-top> <li><a href=#>Link 1</a></li> <li><a href=#>Link 2</a></li> <li><a href=#>Link 3</a></li>

<li><a href=#>Link 4</a></li> </ul> <ul id=menu> <li><a href=#>Inicio</a></li> <li><a href=#>Pgina esttica</a></li> <li><a href=#>Categora</a></li> <li><a href=#>Contctenos</a></li> </ul> </div> <!-- end of logo --> Para esta primera etapa no utilizaremos funciones WordPress, por lo que la ruta al logo es una ruta absoluta y los links de nuestros mens totalmente inventados, a modo de relleno para que nuestro primer trabajo posea algo de contenido y podamos ver la forma que toma. Para las imgenes de relleno utilizaremos el servicio de lorempixum.com, que nos permite tomar imgenes al azar indicando en el link el tamao de las mismas. El index.php comprenda esta seccin: 13

Al inicio de nuestro archivo vamos a llamar al header.php utilizando la funcin get_header(), y al final del mismo debemos insertar el archivo sidebar.php (con get_sidebar() ) y el archivo footer. php (con get_footer() ). <?php get_header(); ?> <div id=nivoslider> <img src=http://lorempixum.com/g/920/310 /> </div><!-- end of nivoslider --> <div id=featured> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3>

<p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> </div><!-- end of featured --> <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> <?php get_sidebar(); get_footer(); ?> El cdigo de sidebar.php: <div id=sidebar> <h3>Ultimas noticias</h3> <ul> <li>Una noticia en la <li>Una noticia en la <li>Una noticia en la <li>Una noticia en la </ul> </div><!-- end of sidebar

14

sidebar<br sidebar<br sidebar<br sidebar<br -->

/>Por />Por />Por />Por

admin</li> admin</li> admin</li> admin</li>

Y el de footer.php, que llevar la funcin wp_footer(), similar a wp_header(). <div id=footer> <ul class=social> <li><a href=#><img src=http://localhost/wp-content/themes/ themetaller/images/skype.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/ themetaller/images/facebook.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/ themetaller/images/twitter.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/

themetaller/images/rss.png /></a></li> </ul> </div><!-- end of footer --> </div><!-- end of content-wrapper --> <?php wp_footer(); ?> </body> </html> Hasta aqu el resultado ser una pgina con datos sin nada de estilo. Vale aclarar que todos los <div> que abrimos, llevan su correspondiente </div> de cierre con un comentario: <! end of nombre-div >. Esta prctica nos ayuda a tener mayor control sobre nuestras etiquetas, puesto que un sitio web puede volverse realmente complejo a medida que aadimos elementos. Cuantos mas comentarios tengamos, mas facil ser para nosotros luego encontrar errores cuando surjan. Adems recomendamos en todo momento hacer uso de la indentacin, separando los bloques de cdigo segn corresponda. Si colocamos themeTaller como el theme por defecto de nuestro WordPress en localhost ya deberamos ver todos los datos e imgenes, uno debajo del otro. Para que realmente tome forma tenemos que aadir el estilo, al cual debemos colocarle los datos del theme y un reset de estilo. /*Theme Name: themeTaller Theme URI: www.summarg.com Author: Nekko Description: themeTaller */ /* RESET */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } :focus { outline: 0; } body { line-height: 1; color: black; background: white;

15

} ol, ul { list-style: none; } table { border-collapse: separate; border-spacing: 0; } caption, th, td { text-align: left; font-weight: normal; } blockquote:before, blockquote:after, q:before, q:after { content: ; } blockquote, q { quotes: ; } Ahora si, procedemos a colocar el color de fondo de la pgina <body>, establecer las dimensiones, el color de fondo y los bordes redondeados de content-wrapper. Para este punto indicamos que nos ayudamos con aplicaciones online como css3generator.com para generar el cdigo CSS3 correspondiente a cada motor de navegador. body { background-color: #2d435a; font-family: arial, sans serif; font-size:12px; } #content-wrapper { width:960px; margin: 10px auto; background-color:white; -webkit-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; overflow:hidden; display:block; } Escribimos el cdigo para los elementos del header: #header { padding: 5px 20px; } #logo img { float:left; width: 261px;

16

height: 53px; padding: 10px 0; } ul#menu-top { height:25px; width:220px; margin-top:0; float:right; } ul#menu-top li a { list-style-type:none; text-decoration:none; float:left; color: #7ec5ff; font-weight:bold; padding: 7px 10px; } ul#menu-top li a:hover { text-decoration:none; background-color: #7ec5ff; color:#fff; font-weight:bold; padding: 7px 10px; } ul#menu { float:left; width: 920px; margin: 0 auto; height:30px; background-image: url(images/menu_bg.png); background-repeat: repeat-x; background-color: #7ec5ff; } ul#menu li a{ float:left; list-style-type:none; text-decoration:none; color:#fff; font-weight:bold; padding: 10px 20px; border-left: 1px solid white; } ul#menu li a:hover { text-decoration:none; background-color: 8ed6ff; color: #f4f4f4; padding: 10px 20px; } Vayan visualizando el sitio para confirmar que cada paso est dado en la direccin correcta.

17

Ahora procedemos a dar estilo al espacio del slider, los bloques de productos-servicios destacados y de las noticias. #nivoslider { float:left; margin: 10px 20px; width: 920px; height: 310px; } #featured { float:left; width: 918px; height: 100px; margin: 0 20px; border: 1px solid #7b7b7b; border-right:none; background-image: url(images/destacado_bg.png); background-repeat: repeat-x; background-color: #dedddd; } .item { width: 295px; padding: 5px; height: 90px; overflow:hidden; border-right: 1px solid #7b7b7b; float:left; } .item h3 { font-family: arial, sans serif; font-weight:bold; font-size: 16px; line-height:30px; color: #7b7b7b; text-align:center; } .item p { font-family: arial, sans serif; font-weight:bold; font-size: 12px; line-height:20px; color: #7b7b7b; text-align:center; } Aqu hacemos un pequeo alto para introducir una aclaracin. Si ustedes visualizan el theme hasta aqu, vern que la tipografa ya no se ve igual que en nuestro PSD, en donde utilizamos la fuente Myriad Pro. Vale aclarar que en clases futuras podemos introducir fuentes mucho ms elegantes utilizando cufn o bien utilizar el servicio de fuentes de Google y @font-face. Seguimos

18

con el estilo de la seccin de noticias. .news { width: 293px; padding: 20px 0 10px 20px; float:left; } .news h2 { font-family: arial, sans serif; font-size: 22px; margin-top:10px; color: #7b7b7b; } .news p { font-family: arial, sans serif; font-size: 12px; line-height:18px; color: #7b7b7b; } Pasamos a dar estilo a los elementos de la sidebar. #sidebar { width: 293px; padding: 20px 20px 10px 0px; float:right; } #sidebar h3 { font-family: arial, sans serif; font-size: 18px; margin-bottom:10px; color: #7b7b7b; } #sidebar ul { list-style-type:none; } #sidebar ul li { padding: 5px 10px; border-bottom: 1px solid #7b7b7b; color: #7b7b7b; } Y finalmente el estilo del footer. #footer { float:left; background: #e6e6e6;

19

width: 920px; padding: 20px; height:100px; } ul.social { list-style-type:none; float:right; width:150px; } ul.social li{ float:left; } Para ir viendo la evolucin del trabajo instalamos un WordPress en SummArg en www.summarg. com/demos/themetaller. Les dejamos los archivos del ejercicio de hoy aqu ThemeTaller clase 3. Sientanse libres de plantear cualquier duda o comentarnos cmo lo haran ustedes tanto aqu como en nuestro foro. Nos vemos en la prxima clase!

20

Clase 4: El bucle y jerarqua de plantillas


El bucle (en ingls The Loop) es el proceso de efectuar bsquedas de determinados parmetros a travs de ciertas condiciones. El bucle mas simple que existe en WordPress es el siguiente: <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> Lo que hace es verificar que en la seccin en donde se ejecuta existan entradas. En caso de ser positivo entonces se ejecuta la sentencia de PHP while, que se encarga de recorrer la base de datos en busca de nuestras entradas mientras have_posts() sea verdadero. Cuando have_posts() ya no encuentre entradas en la seccin, termina el bucle. Cuando mencionamos la seccin, nos referimos a si estamos en la pgina inicial de nuestro WordPress, una categora, una bsqueda por fechas, por autor, o tags. Ahora veamos este mismo bucle en su forma completa. <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> Cdigo que se ejecuta mientras have_posts() sea verdadero. <?php endwhile; else: ?> Cdigo a ejecutarse para el caso de que have_posts() sea falso, es decir que no contenga entradas. <php endif; ?>Fin del bucle Qu cdigo podra ejecutarse mientras have_posts() sea verdadero? En el caso de que existan entradas, lo que podra interesarnos es, por ejemplo, obtener el ttulo de la entrada con link a la misma, el contenido, la fecha de publicacin y el autor. Para ello utilizamos las siguientes funciones: <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_content(); ?> <?php the_time(F jS, Y) ?> <?php the_author() ?> Cada una de estas funciones posee su documentacin en el Codex de WordPress.org, un documento fundamental para aprender a utilizar la enorme cantidad de funciones de la plataforma con sus respectivos parmetros (opciones). El bucle completo quedara de la siguiente manera: <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>> <?php the_title(); ?></a></h2> <?php the_content(); ?> <?php the_time(F jS, Y) ?> <?php the_author() ?> <?php endwhile; else: ?>Lo sentimos, no se han encontrado entradas. <?php endif; ?> La cantidad de entradas por pgina se pueden configurar desde Escritorio > Opciones > Lectura. El bucle expuesto si es ejecutado en la plantilla de inicio de nuestro sitio, arrojar la informacin indicada (ttulo, link, contenido, fecha y autor) de las ltimas 10 entradas, de cualquier categora, una debajo de la otra y de la mas reciente a la mas antigua. Este mismo bucle en otras plantillas, arrojar diferentes resultados. Por ejemplo, para el caso de 21

ser ejecutado el bucle en una plantilla de categora, buscar las ltimas entradas de esa categora especfica. El mismo caso se dar en la plantilla de archivo por fecha (date), archivo por autor (author), etc. Un dato interesante es que WordPress tiene un sistema de jerarqua de plantillas, en donde primero busca una plantilla especfica y si no la encuentra cae en buscar una plantilla mas general para esa misma seccin. En caso de no existir una plantilla determinada, finalmente utilizar la plantilla index.php para mostrar el resultado del bucle de esa seccin.

22

Este esquema es una versin muy simplificada del complejo sistema de plantillas que posee WordPress 3.0 y que pueden visualizar aqu. Para poner en prctica lo visto hoy, insertaremos en nuestro ThemeTaller un bucle sencillo en la plantilla archive.php y veremos como reacciona cuando solicitamos diferentes categoras, archivos por fecha, por autor y tags. Mas adelante nos ocuparemos de personalizar algunas categoras en particular, hacer dos o tres templates diferentes para pginas y varias cuestiones mas. Para poder probar la efectividad del ejercicio tenemos que tener contenidos cargados en nuestro WordPress (en la primer clase vimos como importar algunos contenidos de prueba). Creamos el archivo archive.php y dentro colocaremos: <?php get_header(); ?> <div id=wrapper><?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=dos-tercios listado> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_excerpt(); ?> <?php the_time(F jS, Y) ?> | <?php the_author() ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de bsquedas.</p>

<?php endif; ?> </div><!-- end of wrapper--> <?php get_sidebar(); ?> <?php get_footer(); ?> En este cdigo hemos cambiado the_content() que lista el contenido completo de una pgina, por the_excerpt(), que trae por defecto las primeras 55 palabras sin formato de la entrada. En el CSS aadimos las siguientes lneas: #wrapper {margin-left:20px;margin-top:20px;float:left;width:606px;} .dos-tercios {float:left;margin-bottom:20px;padding: 5px;width:596px;} .listado {border-bottom: 1px solid #7b7b7b;} Esta plantilla servir para ver: categoras, entradas por tags, entradas por autor, entradas por fecha, entradas por taxonoma y por post type. Podemos probar las siguientes URLs en nuestro servidor de pruebas (nosotros colocamos las URLs a nuestro WP de pruebas): http://www.summarg.com/demos/themetaller/?tag=post-formats http://www.summarg.com/demos/themetaller/?author=3 http://www.summarg.com/demos/themetaller/?cat=45 El mismo contenido sirve para los archivos single.php y page.php. Probemos colocar el mismo contenido de archive.php en page.php y en single.php cambiando the_excerpt() por the_content() y solicitemos una pgina. Como resultado tendremos una pgina con su respectivo ttulo, contenido completo, fecha y autor. http://www.summarg.com/demos/themetaller/?page_id=501 Y para avanzar un poco mas con el estilo del theme, podemos aadir valores para las propiedades bsicas que ubicaremos luego de body. Estas sern los headings (h1 a h6), p, a, cite, pre, ul, ol, li, table, etc. a, a:visited {color:#7ec5ff;text-decoration:underline;} a:hover {text-decoration: none;color:#8ed6ff;} small {font: normal 10px arial, Sans-serif;} img {border: none;margin: 3px;} p {font: normal 12px arial, Sans-serif;line-height:18px;padding: 0px 0px 15px 0px;margin: 2px 0;} table, td, tr {font: normal 12px arial, Sans-serif;line-height:18px;} td {padding:5px;} th {font: bold 13px arial, Sans-serif;line-height:18px;padding: 5px;} h1, h2, h3, h4, h5, h6 {color:#7ec5ff;padding:0px;} h1 {font: normal 26px/30px arial, Sans-serif;margin:0 0 5px 0;letterspacing:-1px;} h2 {font:normal 22px/24px arial, Sans-serif;letter-spacing:1px;margin:0 0 5px 0;} h3 {font:normal 20px/22px arial, Sans-serif;margin:0 0 10px 0;} h4 {font:bold 16px/24px arial, Sans-serif;margin:0;} h5 {font:bold 14px/22px arial, Sans-serif;margin:0;} h6 {font:normal 12px arial, Sans-serif;margin:0;} h1 a, h1 a:visited, h2 a, h2 a:visited, h3 a, h3 a:visited {color: #7ec5ff;text-decoration: none;} h1 a:hover, h2 a:hover, h3 a:hover {color: #7ec5ff;text-decoration: none;} h3 a, h3 a:visited, h4 a, h4 a:visited {color: #417394;textdecoration:none;}

23

form {margin:0px;padding:0px;} blockquote {padding: 10px 10px; margin:10px 0px 10px 0px; liststyle:none; border:1px solid #7ec5ff; background-color:#8ed6ff;font: normal 120%/100% Arial, sans serif; } ul{font: normal 12px arial, Sans-serif;list-style:circle;padding:0px; margin:0px;} ol{font: normal 12px arial, Sans-serif;list-styletype:decimal;padding:0px; margin:0px 0px 10px 10px; } li{margin: 0px 0px 0px 10px; padding: 0px;} table, tr, td {font-size:12px;} strong {font-weight:bold;}cite,em,i {font-style: italic;border: none;} pre{font-family:Courier New, Courier, monospace;font-size:12px;lineheight:15px;} En la prxima clase veremos como hacer consultas avanzadas con query_posts() para poder llenar los bloques de informacin del index.php que ya llevamos empezado. Ver el demo de esta clase | Descargar el theme con el ejercicio de esta clase 24

Clase 5: El bucle avanzado: query_posts.


Una de las formas mas fciles de armar un bucle que cumpla con determinadas condiciones es utilizando query_posts. Una consulta con esta funcin altera el bucle a continuacin y puede utilizarse para mltiples bucles si utilizamos correctamente wp_reset_query(). <?php // La consulta query_posts( $args ); // El bucle while ( have_posts() ) : the_post(); echo <li>; the_title(); echo </li>; endwhile; // Reset wp_reset_query(); ?> En nuestra clase de hoy vamos a insertar dentro de themeTaller tres bucles nuevos: Uno para invocar el contenido de tres entradas de la categora Productos destacados y colocarlos debajo de nuestro slider. Buscaremos dos entradas de la seccin noticias para colocar debajo de los productos destacados. En la barra lateral colocaremos las ltimas cuatro entradas de la categora blog.

25

Tomamos la primer seccin en donde colocaremos los productos destacados y encontramos este cdigo HTML segn lo que trabajamos en la Clase 3: <div id=featured> <div class=item>

<h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> <div class=item> <h3>Quiere saber mas?</h3> <p>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...</p> </div><!-- end of item --> </div><!-- end of featured --> Creamos la categora Producto Destacado e insertamos tres entradas con ttulo y un poco de texto (slo unas lneas). Ahora reemplazamos por el bucle con query_posts, en donde los parmetros sern seleccionar tres posts (posts_per_page=3) de la categora Producto Destacado (category_name=Producto Destacado): <div id=featured> <?php query_posts(category_name=Producto Destacado&posts_per_page=3 ); while ( have_posts() ) : the_post(); ?> <div class=item> <h3><?php the_title(); ?></h3> <?php the_content(); ?> </div><!-- end of item --> <?php endwhile; wp_reset_query(); ?> </div><!-- end of featured --> Guardamos y probamos que nuestro theme nos muestre, efectivamente, nuestras tres entradas. Ahora procedemos a elaborar el segundo bucle que ser un poco mas complicado debido a que tiene imgenes con un tamao especfico. Para nuestras imgenes vamos a utilizar la funcin the_post_thumbnail disponible a partir de WP 3+ y que nos ofrece la posibilidad de gestionar miniaturas de tamaos personalizados sin necesidad de plugins. Para activar la funcin deberemos indicarlo en nuestro archivo functions.php, que hasta ahora no vimos, as que creamos un archivo llamado functions.php y dentro colocamos el siguiente contenido: <?php add_theme_support( post-thumbnails ); add_image_size( homepage-thumb, 290, 130, true ); ?> Con add_image_size indicamos a la plataforma que necesitamos un tamao personalizado al que llamaremos homepage-thumb y que deseamos que mida 290px de ancho por 130 de alto. Adems la imagen ser recortada y no redimensionada (el valor true final activa el crop, o re26

corte), de este modo evitamos que algunas imgenes se deformen. Ahora procedemos a crear la categora Noticias y subimos dos entradas las cuales tendrn una imagen que definiremos como destacada. En nuestro archivo index.php buscamos el siguiente cdigo: <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> <div class=news> <img src=http://lorempixum.com/g/290/130 /> <h2>Un post que se destaca...</h2> <p>Sed pharetra risus eu nisi molestie aliquet. Donec ipsum eros, sodales ut convallis ac, posuere vitae orci. <a href=#>Leer ms</a></ p> </div> Y lo reemplazaremos por nuestro segundo bucle, el cual modificaremos para que busque slo dos entradas en la categora Noticias. <?php query_posts(category_name=Noticias&posts_per_page=2 ); while ( have_posts() ) : the_post(); ?> <div class=news> <?php if ( has_post_thumbnail() ) { the_post_thumbnail( homepage-thumb ); } ?> <h2><a href=<?php echo get_permalink(); ?>><?php the_title(); ?></a></ h2> <?php the_excerpt(); ?> </div> <?php endwhile; wp_reset_query(); ?> Observen que en el lugar de la imagen ahora colocamos una llamada a the_post_thumbnail, especficamente a la miniatura homepage-thumb, cuyo valor definimos en el functions.php. Si ustedes desean cambiar el valor de las miniaturas una vez generadas, pueden hacerlo utilizando el plugin Regenerate Thumbnails, ya que una vez que WordPress genera las miniaturas cuando las subimos, no vuelve a regenerarlas al cambiar los valores mediante el functions.php. En nuestro segundo bucle usamos el ttulo (the_title) envuelto en la etiqueta <a> con un href que dentro contiene la funcin get_permalink. El resultado es el ttulo de la entrada con link a la misma. Y en vez de the_content (que nos trae el contenido entero de una nota, con el formato del texto incluido), utilizamos the_excerpt que nos traer las primeras palabras de la entrada sin formato. Los links que colocamos en cada funcin los llevarn directamente al codex de WordPress. org, herramienta fundamental para cualquier desarrollador que quiera avanzar en la creacin de themes o plugins para esta plataforma. Finalmente pasamos a nuestro tercer bucle, ubicado en la barra lateral. Creamos la categora Blog y generamos algn contenido (o reciclamos algo del contenido de pruebas que metimos

27

cambiando de nombre Uncategorized por Blog). Abrimos el archivo sidebar.php que contiene el siguiente HTML. <div id=sidebar> <h3>Ultimas noticias</h3> <ul> <li>Una noticia en la sidebar<br <li>Una noticia en la sidebar<br <li>Una noticia en la sidebar<br <li>Una noticia en la sidebar<br </ul> </div><!-- end of sidebar -->

/>Por />Por />Por />Por

admin</li> admin</li> admin</li> admin</li>

E insertamos nuestro bucle con la nueva categora y solicitando 4 entradas. Tambin aadiremos el nombre del autor de cada entrada desde la funcin the_author. <div id=sidebar> <h3>Ultimas noticias</h3> <ul> <?php query_posts(category_name=Blog&posts_per_page=4 ); while ( have_posts() ) : the_post(); ?> <li><a href=<?php echo get_permalink(); ?>><?php the_title(); ?></a> <br /> Por <?php the_author(); ?></li> <?php endwhile; wp_reset_query(); ?> </ul> </div><!-- end of sidebar --> Vern que en el caso de los ttulos que llevan links ahora los vemos en color celeste y con subrayado debajo. Eso se debe a que nunca definimos desde el style.css como deban verse, as que pasaremos a hacerlo. .news h2 a {color: #7b7b7b;text-decoration:none;} #sidebar ul li a{text-decoration:none;color: #7b7b7b;} Verificamos que se vea todo correctamente en nuestro servidor de pruebas y listo. http://www.summarg.com/demos/themetaller/ themeTaller clase 5 28

Clase 6: el archivo header.php y los mens en WordPress


En la clase 3 hablamos un poco sobre el cdigo bsico que debe ir en el archivo header.php, el cual incluye DOCTYPE, HTML, metas, charset, lenguaje, etc. Adems se vinculan las plantillas de estilo y cualquier script que necesitemos cargar entre etiquetas <head>. Toda pgina necesita tener un ttulo para ser identificada. Vamos a colocar el nuestro utilizando la funcin bloginfo(). Dicha funcin es de uso frecuente en la construccin de themes WordPress y los parmetros mas utilizados (entre otros) son: bloginfo(name) = Devuelve el nombre del blog (se modifica desde Ajustes > General). bloginfo(description) = Devuelve la descripcin del blog (se modifica desde Ajustes > General). bloginfo(site_url) = Devuelve el directorio en donde WP est instalado. bloginfo(stylesheet_url) = Devuelve la ruta a la plantilla de estilos. bloginfo(template_url) = Tambin puede utilizarse template_directory, devuelve la ruta al directorio del theme. Siguiendo con el ttulo, si bien ya estuvimos viendo condicionales, hoy necesitamos profundizar un poquito mas en el tema. En PHP la estructra de un condicional es de la siguiente manera: <?php if (condicin) { Cdigo a ejecutar si la condicin es verdadera } elseif (otra condicin) { Condicin a ejecutar si otra condicin es verdadera else { Cdigo a ejecutar si las condiciones previas no son verdaderas } ?> Entonces con esto presente pasaremos a elaborar un cdigo utilizando conditional tags, que son etiquetas cuya finalidad es ayudarnos a construir condicionales segn seccin que se est mostrando. Nuestro condicional debe decir: Si estamos en el inicio de pgina (is_home) entonces que muestre el nombre del blog, imprimimos | y luego la descripcin del blog. Si estamos en una categora (is_category), entonces imprimir el ttulo de la misma, imprimimos | y el nombre del blog. Si estamos en una entrada (is_single) o en una pgina (is_page), entonces mostrar el ttulo de la entrada, imprimimos | y el nombre del blog. Si ninguna condicin es verdadera, entonces imprimir el ttulo que corresponda (utilizaremos wp_ title()). <title><?php if (is_home () ) { echo bloginfo(name); echo | ; bloginfo(description); } elseif ( is_category() ) { single_cat_title(); echo | ; echo bloginfo(name); } elseif (is_single() || is_page()) { single_post_title(); echo | ; echo bloginfo(name); } else { wp_title(,true); } ?></title> Otra funcin que debemos colocar en nuestro header.php es wp_head(), un hook (gancho) que debe ir entre etiquetas <head></head> y que es utilizado por WordPress para colocar links a recursos y cdigo en general que necesita la plataforma o cualquiera de los plugins que nosotros vayamos instalando. Dicha funcin tiene su equivalente para el pi de pgina, llamado wp_foot29

er(), y son de caracter obligatorios si pretendemos el correcto funcionamiento de nuestra plataforma. Se coloca de la siguiente manera: <head> <?php wp_head(); ?> </head> Aprovechando esta oportunidad, recordemos que en la Clase 3 colocamos la ruta a nuestro logo, en el header.php, de la siguiente manera: <div id=logo> <img src=http://localhost/wp-content/themes/themetaller/images/logo. png /> </div><!-- end of logo --> Ahora que tenemos conocimiento de como funciona bloginfo(), podemos aprovechar y ponerlo en prctica. Reemplazaremos la parte de la ruta que corresponde al theme por la funcin: <div id=logo> <img src=<?php bloginfo(template_url); ?>/images/logo.png /> </div><!-- end of logo --> De este modo la imagen se mostrar correctamente sin importar en que dominio se encuentra instalado el theme. 30

Crear mens con wp_nav_menu()

Finalmente pasaremos a los mens que ahora podemos crear desde el panel de control de forma muy sencilla. Por defecto la funcin no viene activada, sino que debemos hacerlo desde el functions.php de nuestro theme con register_nav_menu (para registrar un nico men) o con register_nav_menus (mltiples mens). Necesitamos dos mens, uno para el #menu-top y otro para el #menu. As que vamos a registrarlos en el functions.php de la siguiente manera: register_nav_menus( array( menu-top => Menu superior, menu => Menu principal )); Guardamos y ahora en el Escritorio nos dirigimos a Apariencia y veremos que aparece la seccin Mens. Creamos dos mens, clickeando en el signo mas en el cuadro derecho. Uno se llamar Menu Top y el otro Menu Principal.

Luego definimos las ubicaciones de cada men. En nuestro caso el nombre coincide con la ubicacin. Guardamos al finalizar.

Y finalmente les colocamos algo de contenido. En nuestro caso, vamos a copiar la estructura que hicimos en el PSD inicial. Recuerden guardar cada men luego de colocados los links. Utilicen las cajas de la izquierda (debajo de Ubicacin del tema) para aadir pginas, categoras o links personalizados.

31

Para mostrar nuestros mens en la plantilla header.php necesitamos de la funcin wp_nav_ menu(). Recordemos la estructura de nuestros mens dentro del HTML generado en la clase 3. <ul id=menu-top> <li><a href=#>Link <li><a href=#>Link <li><a href=#>Link <li><a href=#>Link </ul> <ul id=menu> 1</a></li> 2</a></li> 3</a></li> 4</a></li>

<li><a <li><a <li><a <li><a </ul>

href=#>Inicio</a></li> href=#>P&aacute;gina est&aacute;tica</a></li> href=#>Categor&iacute;a</a></li> href=#>Cont&aacute;ctenos</a></li>

Necesitamos reemplazar las listas desordenadas por nuestros mens recin creados. Comenzaremos por borrar nuestra lista con id #menu-top (desde el <ul> de apertura hasta su </ul> de cierre) y reemplazarla por la funcin wp_nav_menu() con los siguientes parmetros: <?php wp_nav_menu( array( container => false, items_wrap => <ul id=menu-top>%3$s</ul>, theme_location => menu-top )); ?> Estos parmetros, y muchos otros que podemos utilizar, estn explicados en el codex el cual les recomendamos aprender a utilizar por ser la fuente principal de aprendizaje para cualquier desarrollador de themes y plugins. Container nos permite definir el tipo de contenedor en que se coloca al menu, permite elegir entre div, nav y false, el cual deshabilita la funcin (fue nuestra eleccin. Items_wrap nos permite indicarle al men las caractersticas que tendr la etiqueta que envuelva al men y Theme_location nos permite seleccionar el men que colocaremos en esta posicin (definido en el functions.php). Ahora haremos lo mismo con el men principal. <?php wp_nav_menu( array( container => false, items_wrap => <ul id=menu>%3$s</ul>, theme_location=> menu, )); ?> Dentro de uno de los items del men, en nuestro caso de Blog, aadiremos algunas categoras o pginas hijas. 32

Para que funcione correctamente, utilizaremos un poco de jQuery, librera que podemos descargar desde jQuery.com. En el archivo functions.php, hacia el final, aadimos: /* Mi jQuery */ function my_init_method() { if (!is_admin()) { wp_deregister_script( jquery ); wp_register_script( jquery, /wp-content/themes/themetaller/scripts/ jquery.min.js); wp_enqueue_script( jquery ); } } add_action(init, my_init_method); Colocaremos el archivo jquery.min.js en nuestra carpeta scripts, y luego aadimos dentro de las etiquetas <head> las siguientes lneas: <script type=text/javascript> $(document).ready(function() { $(#menu ul).css({display: none}); $(#menu li).hover(function(){ $(this).find(ul:first).css({visibility: visible,display: none}). show(300); },function(){ $(this).find(ul:first).css({visibility: hidden}); }); }); </script> Y en nuestro CSS eliminamos las lneas antiguas que hacan referencia a #menu y las reemplazamos por estas: /* Menu desplegable */ #menu { float:left; width: 940px; margin: 0; padding:0px; height:35px; background-image:url(images/menu_bg.png); background-repeat: repeat-x; background-color: #7ec5ff; position:relative; z-index:300; list-style-type:none; } #menu ul { list-style-type:none; } #menu a { float:left; display:block; text-decoration:none; 33

color:#fff; font-weight:bold; padding: 10px 25px 10px 10px; border-right: 1px solid white; } #menu a:hover { color:#fff; background: #8ed6ff; } #menu li { float:left; position:relative; } #menu ul { position:absolute; display:none; width:160px; top: 35px; left: -10px; } #menu ul a { float:left; background: #7ec5ff; border: 1px solid white; border-top:none; } #menu li ul{ border-top: 1px solid white; } #menu li ul a { width:150px; height:auto; } #menu ul ul { top:auto; } #menu li ul ul { margin:0px 0 0 10px; } #menu li:hover ul ul, #menu li:hover ul ul ul, #menu li:hover ul ul ul ul { display:none; } #menu li:hover ul, #menu li li:hover ul, #menu li li li:hover ul, #menu li li li li:hover ul { display:block; } Ahora el nuevo men debera estar funcional. Clase 6

34

35

Clase 7: Insertar un slider sin utilizar plugins


En esta clase aprenderemos a insertar un slider si la necesidad de echar mano a ningn plugin. Consideramos que esta leccin conforma un excelente punto de partida para aprender a utilizar los cientos de recursos jQuery realmente asombrosos que circulan por la web. Antes que nada vale mencionar que jQuery es un framework (una librera) para facilitar animaciones y funciones del lado del cliente. Es totalmente gratuito y ya viene en el core de la mayora de los CMS. Generalmente agregando un plugin (un slider, un news ticker o un men) insertamos un mundo nuevo de funciones con muy poco trabajo. Los plugins de jQuery no se instalan desde el apartado Plugins de WordPress, sino que bastar con colocar el o los archivos en nuestro theme y linkearlos desde el header.php, footer.php o functions.php. Tenemos dos versiones para descargar en jQuery.com: una llamada de produccin y la otra de desarrollo. En nuestro caso no estamos interesados en desarrollar nada, simplemente utilizaremos recursos ya fabricados, as que descargamos la versin de produccin que est minimizada y comprimida. El archivo jquery-1.7.2.min.js (actual) posiblemente se abra en nuestro navegador y nosotros procederemos a guardarlo en una carpeta llamada /scripts/ dentro de nuestro theme. En la clase anterior utilizamos jQuery para el men, as que en nuestro proyecto ya est almacenado. Tambin indicamos a WordPress que deseamos utilizar nuestro archivo jQuery desde el functions.php. /* Mi jQuery */ function my_init_method() { if (!is_admin()) { wp_deregister_script( jquery ); wp_register_script( jquery, /wp-content/themes/themetaller/scripts/ jquery-1.7.2.min.js); wp_enqueue_script( jquery ); } } add_action(init, my_init_method); Notarn que my_init_method comienza con un condicional en donde especifica que si no estamos en el rea de administrador, entonces carga nuestro jQuery. Esto se debe a que WordPress ya trae la librera y, como dijimos anteriormente, y lo utiliza para el Escritorio. Si nosotros linkeasemos la librera desde el header.php del theme sin ningn miramiento ni condicionales, posiblemente algunas secciones del Escritorio dejen de funcionar con normalidad, ya que cargara dos versiones de jQuery y sto producira errores.

36

Nivo-Slider, uno de los sliders jQuery mas populares

En el sitio oficial de Nivo-Slider promocionan la venta de un plugin para WordPress que es por dems fantstico. Tambin en el repositorio oficial vimos algn que otro plugin para insertar el slider en WordPress bastante bien logrado. Pero nosotros no tomaremos esos caminos, sino que nos ensuciaremos un poco para entender como se aplican estos fantsticos recursos a nuestro theme. Primero descargamos Nivo Slider desde su sitio (desde aqu, selecciona la primer opcin llamada jQuery Plugin) y copiaremos la carpeta themes, el archivo jquery.nivo.slider.pack.js y nivo-slider. css a nuestra carpeta /scripts/.

37

Y ahora linkeamos nivo-slider.css y el estilo themes/default.css desde nuestro header.php utilizando parte de la ruta hasta nuestro theme con bloginfo(), como vimos en clases pasadas. <link rel=stylesheet type=text/css href=<?php bloginfo(template_ url); ?>/scripts/nivo-slider.css media=screen /> <link rel=stylesheet href=<?php bloginfo(template_url); ?>/ scripts/themes/default/default.css type=text/css media=screen /> Y en el footer.php vamos a linkear el archivo JS, justo antes del cierre de la etiqueta </body>. Tambin vamos a dejar preparado el script indicndole que queremos que se active en el <div> con id #nivoslider. <script type=text/javascript src=<?php bloginfo(template_url); ?>/ scripts/jquery.nivo.slider.pack.js></script> <script type=text/javascript> $(window).load(function() { $(#nivoslider).nivoSlider(); }); </script> Antes de continuar vamos a establecer el tamao de las imgenes que utilizaremos con the_ post_thumbnail(). En functions.php ubicamos nuestra seccin destinada a las imgenes. add_theme_support( post-thumbnails ); add_image_size( homepage-thumb, 290, 130, true ); Y debajo aadimos un tamao mas, con el nombre de homepage-slider. add_image_size( homepage-slider, 920, 310, true ); Guardamos y subimos al servidor. Ahora al subir una imagen, WordPress recortar este tamao extra. Generamos la categora slider y subimos dentro tres o mas entradas con su respectivo ttulo y una imagen que mnimo sea de 920px de ancho por 310px alto, las cuales marcaremos

como destacadas. No es necesario que las insertemos en la entrada, con slo marcarlas como destacadas ya alcanza.

38 Procedemos a abrir nuestro archivo index.php en donde vamos a trabajar desarrollando las primeras lneas: <div id=nivoslider> <img src=http://lorempixum.com/g/920/310 /> </div><!-- end of nivoslider --> El slider trae un archivo demo.html para que podamos copiar la estructura que necesita para funcionar. Lo copiamos dentro de nuestro id #nivoslider y vamos dejando libre la seccin en donde colocaremos el cdigo PHP para generar una consulta que traiga nuestras imgenes recin subidas. <div id=nivoslider> <div class=slider-wrapper theme-default> <div class=ribbon></div> <div id=slider class=nivoSlider> <!-- aqui va nuestra query... --> </div> </div> </div><!-- end of nivoslider --> Necesitamos efectuar una consulta que nos traiga tres entradas de la categora slider, y cuando lo haga deber mostrarnos la miniatura del tamao que le especificamos (homepage-slider) en el functions.php usando add_image_size. Adems la imagen debe estar entre etiquetas <a></a> y el link debera dirigirnos a la entrada que se est mostrando. El cdigo finalmente quedar de la siguiente manera: <div id=slider> <div class=slider-wrapper theme-default> <div class=ribbon></div> <div id=nivoslider class=nivoSlider> <?php query_posts(category_name=slider&posts_per_page=3 ); while ( have_posts() ) : the_post(); ?> <a href=<?php echo get_permalink(); ?>><?php the_post_thumbnail( homepage-slider ); ?></a>

<?php endwhile; wp_reset_query(); ?> </div> </div> </div><!-- end of nivoslider -->

39 Finalmente podemos observar que el theme por defecto de Nivo Slider nos agrega debajo un control para navegar, lo eliminaremos abriendo su archivo de estilos ubicado dentro de nuestro theme/scripts/theme/default/default.css, buscamos la lnea 30 y le aadimos un display:none para ocultarlo. .theme-default .nivo-controlNav { display:none; position:absolute; left:50%; bottom:-42px; margin-left:-40px; } Esperamos que les haya resultado fcil de entender esta clase y les recomendamos que utilicen el complemento Firebug (para Firefox) para ejercitar con otros scripts similares a Nivo Slider para afianzar conocimientos. Clase 7

Clase 8: Sidebars y widgets


Hoy vamos a trabajar con el archivo sidebar.php y con reas de widgets. Los widgets son pequeos mdulos que se pueden aadir en sectores de nuestra eleccin y que tienen mltiples funciones. Por defecto WordPress nos ofrece un widget con un calendario, uno para mostrar pginas creadas, otro para categoras, mens, texto plano u HTML, links del blogroll, suscripcin a feeds, campo de bsqueda, links administrativos, etc. Nosotros podemos aadir muchos mas mediante plugins.

40

Los widgets pueden agregarse a cualquier plantilla de nuestra web y combinado con condicionales, los cuales vimos en la Clase 6, nos dan un sinfn de posibilidades para nuestro sitio. Para aadir un widget hace falta primero declararlo en nuestro functions.php, y luego insertarlo en la plantilla deseada. Vamos a generar un rea de widgets bsico para la sidebar. register_sidebar(array( name => Sidebar, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); El primer parmetro, name, asigna un nombre a nuestro widget que figurar luego en nuestro escritorio bajo Widgets para poder identiticarlo. before_widget y after_widget aade etiquetas al inicio y al final del mismo, en nuestro caso abrimos un div con class widget y lo cerramos. Finalmente repetimos la misma operacin pero para el ttulo con before_title y after_title. La funcin register_sidebar tambin admite los parmetros id (para colocar un ID al widget) y description (descripcin). Guardamos el archivo functions.php con estas lneas que acabamos de explicar y vemos si aparece el nuevo rea de widgets en Apariencia > Widgets. Hoy vamos a generar tres reas de widgets para utilizar en tres secciones diferentes: una sidebar en el inicio, otra para la plantilla de categoras y otra para una pgina. Las haremos idnticas entre si pero con diferentes nombres.

register_sidebar(array( name => Sidebar Home, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); register_sidebar(array( name => Sidebar Categoria, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); register_sidebar(array( name => Sidebar Pagina, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); Hasta ahora venimos trabajando con una sola sidebar y vamos a explotar su uso todo lo que podamos. Abrimos el archivo y colocamos luego del listado de entradas que colocamos y antes del </div> de cierre del div #sidebar: <?php if ( !function_exists(dynamic_sidebar) || !dynamic_ sidebar(Sidebar Home) ) : endif; ?> Con eso slo estamos insertando los widgets que cargemos dentro de la seccin Sidebar Home, pero faltara indicarle que queremos que se cargue dichos widgets si y slo si estamos visualizando el home. Echamos mano a los Condicional Tags, como ya mencionamos. Entonces reemplazamos el cdigo por este nuevo. <?php if (is_home()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Home) ) : endif; } ?> Probamos aadir un campo de bsqueda o lo que sea para ver si se visualiza en el home y comprobamos que no se visualice en la vista por categoras o en una pgina.

41

Perfecto! Ahora generamos el cdigo con sus respectivos condicionales para el rea de widgets a mostrarse en el caso de estar en una categora (is_category) y en una pgina (is_page). <?php if (is_home()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Home) ) : endif; } elseif (is_category()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Categoria) ) : endif; } elseif (is_page()) { if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Pagina) ) : endif; } ?> Guardamos, activamos diferentes widgets en cada rea y confirmamos que cada sidebar muestre lo que nosotros queremos. De acuerdo a lo que escribimos en nuestro functions.php el cdigo HTML de cada widget qued de la siguiente manera: <div class=widget> <h3>Busqueda</h3> <!-- contenido del widget seleccionado --> </div> Aplicamos un estilo diferente al widget para diferenciarlo de otros contenidos aadiendo un margen inferior, color de fondo, color de borde, borde redondeado y padding. .widget { margin-bottom: 20px; -webkit-border-radius: 5px; border-radius: 5px; background: #f4f4f4; border: 1px solid #ececec; padding: 5px; } 42

Doble sidebar

A nuestro template de pgina le vamos a agregar una segunda sidebar, slo por el gusto de ver como funciona el asunto. Abrimos el archivo page.php y observamos que en la anteltima lnea se utiliza una funcin para incluir la sidebar all. Duplicaremos dicha funcin pero esta vez insertando entre comillas simples el nombre de nuestra nueva sidebar, que en este caso se llamar dos. <?php get_sidebar(); get_sidebar(dos); ?>

Ahora necesitamos crear el archivo de dicha sidebar y para nombrarlo debemos tener en cuenta que primero colocamos sidebar-nombreelegido.php. El nombreelegido es lo que colocamos entre comillas simples cuando invocamos al archivo con get_sidebar. En nuestro caso el archivo deber llamarse sidebar-dos.php. Coloquemos dentro el siguiente contenido. <div id=sidebar> <?php if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar

Dos) ) : endif; ?> </div><!-- end of sidebar --> Generamos esta nueva rea de widgets en el functions.php. register_sidebar(array( name => Sidebar Dos, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); Y para que haya un poco de coherencia en el diseo, vamos a modificar los ids de page.php para generar un CSS para este layout. <div id=wrapper-dos> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_content(); ?> <?php the_time(F jS, Y) ?> | <?php the_author() ?> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de b&uacute;squedas.</p> <?php endif; ?> </div><!-- end of wrapper--> Aadimos en el CSS las propiedades para #wrapper-dos y #sidebar-dos. #wrapper-dos { width:392px; float:left; margin-top:20px; margin-left:20px; } #sidebar-dos{ width: 215px; margin-top:20px; margin-right:20px; float:right; } Y vamos a darle un poco de formato a las listas dentro de widget, ya que nuestros widgets las usan mucho. .widget li { list-style-type:none; padding: 0 0 0 10px; } 43

Nuestro ejercicio de hoy no ha quedado muy bonito que digamos, pero espero que la idea haya sido lo mas clara posible. Pueden agregar tantas reas de widgets como quieran y tantas sidebars como sean necesarias.

44

Clase 8

Clase 8 Anexo: Sidebar horizontal


A pedido de uno de los lectores que viene siguiendo el curso, aadimos un anexo a la clase 8, dedicada a sidebars, para explicar como maquetar una tercera sidebar pero de modo horizontal. Vamos a seguir experimentando con las sidebars dentro de la plantilla page.php que ya tiene dos sidebars dispuestas de la siguiente manera. Antes de continuar les recomendamos leer un poco sobre la propiedad float (aqu hay un buen tutorial en espaol). Bsicamente esta propiedad es la encargada de indicarle a un contenedor hacia donde debe ubicarse, lo que requiere para su correcta ubicacin es un ancho fijo y espacio libre en la direccin deseada.

45

En el trabajo que ya tenemos hecho, nuestras dos sidebars tienen ancho fijo y flotan hacia la derecha (float:right). Es importante remarcar que las sidebars se ubican en el primer espacio libre encontrado en la direccin indicada desde float. Nosotros ubicamos el contenido a la izquierda, por eso queda disponible el espacio derecho para nuestros widgets. #sidebar { width: 293px; margin-top:20px; margin-right:20px; float:right; } #sidebar-dos{ width: 215px; margin-top:20px; margin-right:20px; float:right; } Al tener las sidebars los anchos que deseamos, los contenedores con class .widget no lo necesitan, ya que flotarn con el mismo ancho de su contenedor padre en direccin vertical. .widget { margin-bottom: 20px; -webkit-border-radius: 5px; border-radius: 5px; background: #f4f4f4;

border: 1px solid #ececec; padding: 5px; } Ahora lo que tenemos que lograr es insertar una tercera sidebar, debajo de todo el contenido pero arriba del footer, que ocupe todo el ancho de la pgina y que tenga tres widgets adentro.

46

La tercera sidebar se ubicar dentro de un archivo que llamaremos sidebar-horizontal.php y la llamada a la misma dentro de page.php se realiza de la siguiente forma: <?php get_sidebar(); get_sidebar(dos); get_sidebar(horizontal); ?> Dentro de sidebar-horizontal.php colocaremos dos reas con contenido de pruebas y en el tercer espacio repetiremos un rea de widgets (ustedes ya saben como agregar reas nuevas!). <div id=sidebarHorizontal> <div class=widget> <h3>Area uno</h3> <ul> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> </ul> </div> <div class=widget> <h3>Area dos</h3> <ul> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> </ul> </div> <?php

if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Sidebar Categoria) ) : endif; ?> </div><!-- end of sidebarHorizontal --> Y finalmente el toque mgico para que tome la forma deseada: el cdigo CSS. Primero damos el ancho total que va a tener el rea contenedor de los widgets, los mrgenes (20px de cada lado excepto del izquierdo) y le indicamos que se ubique en el primer espacio libre a la izquierda que encontramos puesto que de lo contrario los elementos dentro de ubicarn fuera del rea deseada. #sidebarHorizontal{ width: 920px; margin:20px; float:left; } Luego procedemos a indicarle al elemento .widget que, slo cuando se encuentra dentro del rea #sidebarHorizontal, debe tener un determinado ancho fijo, ubicarse en el primer espacio libre a la izquierda (float:left;) y tener un margen a la izquierda de 20px. #sidebarHorizontal .widget { width:281px; float:left; margin-left:20px; } Y listo! Pueden experimentar colocar esta nueva sidebar debajo del header, en la plantilla index. php o en donde se les ocurra. Clase 8 Anexo 47

Clase 9: el archivo footer.php


El archivo footer.php cumple una funcin similar al header.php en cuanto a que sirve para cargar scripts y archivos pertenecientes a plugins, tal como indicamos en la Clase 6. En dicho archivo colocamos tres cosas fundamentales: la funcin wp_footer(), el cierre de la etiqueta <body> y el cierre de la etiqueta <html>. La funcin wp_footer() es utilizada por muchos plugins para cargar plugins y scripts en general que deban ir al final de la pgina por sus caractersticas de programacin o para no demorar la carga de determinados contenidos de la pgina. <?php wp_footer(); ?> </body> </html> La mayora de los diseos web tienen un pie de pgina bien definido en donde casi siempre podemos encontrar: El copyright y/o leyenda del diseador ltimos comentarios ltimas noticias ltimos mensajes en redes sociales Informacin de contacto (e incluso algn formulario de contacto pequeo) Una barra de navegacin secundaria Publicidades etc. Nosotros vamos a intentar incorporar un rea de widgets, en uno de los cuales insertaremos nuestros conos sociales, un men al final de la pgina que sea rplica del men princial pero con un estilo diferente, y un link para volver al inicio que animaremos con jQuery.

48

Area de widgets

Hasta ahora en el div #footer tenemos lo siguiente: <div id=footer> <ul class=social> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/skype.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/facebook.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/twitter.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/rss.png /></a></li> </ul> </div><!-- end of footer -->

Vamos a modificarlo para que dentro haya tres reas de widgets. En la primera colocaremos cualquier contenido a modo de pruebas, en la segunda colocaremos un rea de widgets que crearemos para esta seccin y en la tercera dejaremos los conos sociales. Primero colocamos el cdigo para crear nuestro rea de widgets en el functions.php. register_sidebar(array( name => Widget Footer, before_widget => <div class=widget>, after_widget => </div>, before_title => <h3>, after_title => </h3>, )); Y ahora todo el contenido del #footer. <div id=footer> <div class=widget> <h3>Footer</h3> <ul> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> <li>Contenido de prueba</li> </ul> </div> <?php if ( !function_exists(dynamic_sidebar) || !dynamic_sidebar(Widget Footer) ) : endif; ?> <ul class=social> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/skype.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/facebook.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/twitter.png /></a></li> <li><a href=#><img src=http://localhost/wp-content/themes/themetaller/images/rss.png /></a></li> </ul> </div><!-- end of footer --> Las rutas a los conos sociales deben arreglarse para que funcionen cuando el theme est instalado en cualquier sitio web, por lo que necesitamos usar la funcin bloginfo() para lograr que stas sean dinmicas. <ul class=social> <li><a href=#><img src=<?php bloginfo(template_url); ?>/images/ skype.png /></a></li> <li><a href=#><img src=<?php bloginfo(template_url); ?>/images/facebook.png /></a></li> <li><a href=#><img src=<?php bloginfo(template_url); ?>/images/ twitter.png /></a></li>

49

<li><a href=#><img src=<?php bloginfo(template_url); ?>/images/ rss.png /></a></li> </ul> El resultado es un rea de widgets que tiene fondo gris, como los que agregamos anteriormente en las sidebars.

Sera bueno que los widgets del footer tengan su propio estilo, por lo que aadimos un nuevo estilo para todo .widget que se encuentre dentro de #footer de la siguiente manera: #footer .widget { width:281px; float:left; margin-left:20px; background:none; border:none; padding:0; } #footer .widget h3{ color: #7b7b7b; border-bottom: 2px solid #fff; padding-bottom: 5px; margin-bottom:5px; width:281px; float:left; margin-left:20px; text-shadow: 0px 0px 2px #bdbdbd; filter: dropshadow(color=#bdbdbd, offx=0, offy=0); } #footer .widget p, #footer .widget a, #footer .widget li{ color: #7b7b7b; text-decoration:none; } #footer .widget a:hover { text-decoration:underline; } Al ttulo h3 del widget notarn que le agregu text-shadow. Pueden agregar toda clase de efectos geniales con CSS3 usando este generador de cdigo css3generator.com. Quienes tengan navegadores actualizados a las ltimas versiones podrn ver los nuevos efectos, y quienes tengan navegadores mas antiguos vern simplemente el texto sin el efecto, completamente funcional. Los conos sociales quedaban en dos lneas porque el contenedor resultaba muy angosto, por lo

50

que aumentamos el width y ya caben perfectamente. ul.social { list-style-type:none; float:right; width:190px; padding:0px; margin:0px; }

51

Men adicional

No resulta mala idea aadir un men al pie de pgina. Ayuda a que el sitio resulte mas fcil de navegar. Por eso vamos a repetir nuestro Men Principal debajo pero definitivamente debemos modificar el estilo del mismo. Vamos a utilizar el id #menuFooter para la etiqueta <ul>, as que modificamos y pegamos el siguiente cdigo antes del cierre del div #footer. <?php wp_nav_menu( array( container => false, items_wrap => <ul id=menuFooter>%3$s</ul>, theme_location=> menu, )); ?> Para este segundo men no vamos a colocar los submens desplegables debido a que para que funcione correctamente necesitamos pasar un valor fijo para un alto que no conocemos, por lo que ahora evitaremos entrar en un script para calcular cuanto debe trasladarse el submen y que se abra como corresponde. Hecha esta aclaracin, le damos estilo a la nueva clase #menuFooter. #menuFooter { -webkit-box-shadow: inset 0px 3px 1px 0px #ccc; box-shadow: inset 0px 3px 1px 0px #ccc; width: 960px; background: #e1e1e1; border:none; margin: 10px 0 0 0; -webkit-border-radius: 0px 0px 10px 10px; border-radius: 0px 0px 10px 10px; list-style-type:none; float:left; height:35px; } #menuFooter a {

float:left; display:block; text-decoration:none; color:#666; font-weight:bold; margin-left:10px; padding: 10px; border-right: none; background: none; } #menuFooter a:hover { color:#666; background: #f4f4f4; } #menuFooter ul { background:none; list-style-type:none; } #menuFooter li ul { display:none; } #menuFooter ul a { float:left; } Y modificamos el padding de #footer. #footer { float:left; background: #e6e6e6; width: 960px; padding: 20px 0 0 0; }

52

Volver arriba

El usuario hizo scroll luego de revisar mucho texto y lleg hasta nuestro footer, si necesita volver al inicio de la pgina para usar el men desplegable completo o el men top, nosotros podemos hacerle la tarea mas fcil si le ofrecemos al pi un link que diga volver arriba o similar. En nuestro caso, deseamos colocar el link en la misma barra en donde est el men del footer, slo que alineado a la derecha para separarlo de los items del men. Para eso lo agregamos como un elemento mas de la lista #menuFooter pero con una clase diferente. Modificamos las lneas en donde insertamos el men de la siguiente manera:

<?php wp_nav_menu( array( container => false, items_wrap => <ul id=menuFooter>%3$s<li class=toTop><a href=#top>Volver arriba</a></li></ul>, theme_location=> menu, )); ?> De este modo al final de la lista que conforma el men, metemos el elemento con clase .toTop y dentro un link con href #top. Aprovechando que estamos en la plantilla footer.php, aadimos las siguientes lneas de jQuery luego de las que ya figuran de nivoslider entre etiquetas <script>. $(document).ready(function() { $(a[href=#top]).click(function(){ $(html, body).animate({scrollTop:0}, slow); return false; }); }); Y finalmente necesitamos indicar en nuestro CSS que el <li> con class .toTop debe flotar a la derecha. .toTop { float:right; }

53

Clase 9

Clase 10: La plantilla de entrada y de comentarios


Las plantillas de vista de entrada son parte esencial del look and feel de un sitio y deben tener un espacio amplio para poder colocar dentro cualquier tipo de contenido (texto, imgenes, videos, descargas, etc). Esta clase, con un poco de suerte, les resultar muy fcil de entender ya que estuvimos viendo los conceptos que trataremos a continuacin pero aplicado a otras plantillas. Al visualizar una entrada, WordPress buscar primero la plantilla single.php, y en caso de no encontrarla pasar a mostrar el contenido utilizando la plantilla index.php. Les recuerdo que pueden encontrar una muy buena grfica sobre jerarquas de plantilla en el sitio oficial.

Single.php, layout y contenido

Es la plantilla para la vista individual de una entrada y su estructura bsica es como muestra la siguiente imagen.

54

Pasamos en limpio lo que vamos a hacer: llamamos al header, en el rea de contenidos usamos las funciones the_title (el ttulo) y the_content (el contenido), luego llamamos a la sidebar y finalmente al footer. Para que the_title y the_content puedan traernos contenido desde la base de datos correspondiente al ID de la entrada que estamos consultando, necesitamos colocarlos dentro del bucle. Esto se traduce en el siguiente contenido (que es el que ya tenemos desde la clase 4). <?php get_header(); ?> <div id=wrapper> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=dos-tercios listado> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_content(); ?> </div><!-- end of dos-tercios -->

<?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de b&uacute;squedas.</p> <?php endif; ?> </div><!-- end of wrapper--> <?php get_sidebar(); ?> <?php get_footer(); ?>

55

La funcin the_content nos trae todo el contenido publicado en una entrada: su texto, imgenes, galeras, listas, etc. Y para aprovechar la oportunidad aqu es en donde necesitamos definir la alineacin de las imgenes que, tal como el editor de WordPress lo seala al subir una imagen, la posicin de las mismas puede ser centrada respecto del texto, a la izquierda del texto, a la derecha del texto o sin bordear por texto. Esto se traduce en el siguiente CSS. /* alignments */ .center {text-align: center;} img.center, img[align=center] {display: block;margin-left: auto;margin-right: auto;} .alignleft {float: left;} img.alignleft, img[align=left] {float:left;margin: 2px 10px 5px 0px;} .alignright {float: right;} img.alignright, img[align=right] {float:right;margin: 2px 0px 5px 10px;} .clear {clear:both;} hr.clear {clear:both;visibility: hidden;margin: 0px;padding: 0px;height:0px;} Generalmente en la vista de entrada tambin se suele colocar informacin como la fecha de publicacin, en qu categora se encuentra, etiquetas, cantidad de comentarios y el autor. Y para esta seccin nos vamos a ayudar con algunos conos para que la seccin luzca lo mejor posible. En este caso nos decidimos por este set de conos genial llamado gcons. Vamos a construir debajo del cierre del contenedor .dos-tercios, un contenedor con class .metabox en donde colocaremos todas las funciones dentro de etiquetas span para luego insertarles algn cono. Utilizaremos las siguientes funciones: the_category, the_time, the_author_posts_link, comments_popup_link y the_tags (cada funcin tiene su link al codex, aprendan a consultarlo). <div class=metabox> <span class=time meta>Publicado el <?php the_time(j) ?> de <?php the_time(F, Y) ?> | </span><span class=author meta>Por <?php the_author_posts_link(); ?> | </span>

<span class=comments meta><?php comments_popup_link(Sin Comentarios, 1 Comentario, % Comentarios); ?> | </span><span class=category meta>En la categor&iacute;a <?php the_category( ); ?> | </span> <span class=tags meta>Con las siguientes etiquetas <?php the_tags(); ?></span> </div> El resultado, sin ningn tipo de estilo aplicado:

Los conos gcons tienen un set en color azul. Tomamos algunos para utilizar en nuestros spans y los llevamos a tamao 16px x 16px con Photoshop o algn programa de edicin. Al .metabox le colocamos un color azul oscuro, tipografa de color blanco, bordes redondeados y un padding para que no queden pegados al borde los elementos que ubicamos dentro. .metabox { padding: 10px; background: #2d435a; color:white; -webkit-border-radius: 10px; border-radius: 10px; margin: 10px 0; display:block; float:left; } La clase .meta se repetir luego dentro de cada span, los cuales tienen dos clases (ej. class=category meta suma dos clases, .category y .meta), por eso colocamos las propiedades background-repeat y background-position, que modificarn el cono que insertaremos luego en la otra clase de cada span. Colocamos tambin un padding-left para que el texto deje un espacio para que se vea el cono. .meta { background-repeat: no-repeat; padding-left:20px; margin-bottom: 4px; float:left; height:16px; background-position: center left; } Y colocamos el link a cada cono. .time { background-image: url(images/calendar.png); } .author{

56

background-image: } .comments { background-image: } .category { background-image: } .tags{ background-image: }

url(images/agent.png); url(images/chat-.png); url(images/connections.png); url(images/tag.png);

Este es el resultado de nuestro trabajo.

57

os comentarios

Ahora podemos insertar el llamado a la plantilla de comentarios. Bastar con colocar la siguiente funcin dentro del bucle (o sea, antes del endwhile). <?php comments_template(); ?> Y automticamente veremos el siguiente contenido.

Si nos fijamos en el cdigo, el HTML generado es el siguiente: <ol class="commentlist"> <li class="comment byuser comment-author-admin bypostauthor even thread-even depth-1" id="comment-31"> <div id="div-comment-31" class="comment-body"> <div class="comment-author vcard"> <img alt='' src='http://0.gravatar.com/avatar/a1b6b0dc561b8146fba62 24e6c71a1be?s=32&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad5165 03a11cd5ca435acc9bb6523536%3Fs%3D32&amp;r=G' class='avatar avatar-32 photo' height='32' width='32' /> <cite class="fn">admin</cite> <span class="says">dice:</span> </div> <div class="comment-meta commentmetadata"><a href="http:// localhost/?p=694#comment-31"> 19 mayo, 2012 a las 23:56</a>&nbsp;&nbsp;<a class="comment-edit-link" href="http://localhost/wp-admin/comment.php?action=editcomment&amp;c=31" title="Editar comentario">(Editar)</a> </div> <p>Hola! Este es un comentario <img src='http://localhost/wp-includes/ images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p> <div class="reply"> <a class='comment-reply-link' href='/?p=694&#038;replytocom=31#respond' onclick='return addComment.moveForm("div-comment-31", "31", "respond", "694")'>Responder</a> </div> </div> </li> </ol> Claro que podemos simplificar un poco si sabemos a lo que apuntamos y podemos ignorar algunas clases muy especficas como .bypostauthor en nuestra etiqueta <li>. La estructura bsica que vamos a tomar es la siguiente: <ol class="commentlist"> <li> <div class="comment-author"> <img alt='' src='/link/a/gravatar/' height='32' width='32' /> <cite class="fn">admin</cite> <span class="says">dice:</span> </div> <div class="comment-meta"><a href="http://localhost/?p=694#comment-31"> 19 mayo, 2012 a las 23:56</a>&nbsp;&nbsp;<a href="link/a/editar" title="Editar comentario">(Editar)</a> </div> <p>Hola! Este es un comentario</p> <div class="reply"> <a class='comment-reply-link' href='/link/para/responder'>Responder</a> </div> </li> </ol> Qu sucedi? Simplificamos. Eliminamos clases que no necesitabamos declarar as como una etiqueta div que contenia a todo el comentario y que resultaba innecesario para un estilo bsico.

58

Ahora colocamos las clases y etiquetas correspondientes en el CSS. Al inicio de mi nueva seccin coloco entre /* y */ un comentario para utilizar de referencia a futuro. Lo nico que agregu que no estaba en el HTML es la clase .comment-awaiting-moderation, que aparece cuando un mensaje est pendiente de moderacin, tal como lo dice su nombre. /* Comments! */ ol.commentlist {} ol.commentlist li {} .comment-author {} .comment-author img {} .fn {} .says {} .comment-meta {} .comment-awaiting-moderation {} .comment-meta a {} ol.commentlist li p {} .reply a {} Es importante destacar que vamos a trabajar con comentarios anidados (o sea que puedo responder al comentario de alguien y mi comentario aparecer debajo del mismo) y del modo en que lo estamos maquetando aparecer un comentario dentro del otro. As que lo mejor es utilizar anchos que no sean fijos, sino relativos (o sea que cubran determinado porcentaje del contenedor padre). /* Comments! */ ol.commentlist { list-style-type: none; width:600px; } ol.commentlist li { width:95%; position:relative; overflow:hidden; background: #e1e1e1; -webkit-border-radius: 10px; border-radius: 10px; border: 1px solid #ccc; padding:10px; margin: 10px 0; } .comment-author { width: 60%; float:left; height:40px; } .comment-author img { float:left; border: 1px solid #ccc; margin: 2px; } .fn { color: #2d435a; font-weight:bold;

59

font-size:14px; } .says {} .comment-meta { width: 40%; float:left; height:40px; text-align:right; overflow:hidden; } .comment-awaiting-moderation { position:absolute; left:0px; top:10px; width:100%; margin-right:10px; text-align:right; } .comment-meta a {} ol.commentlist li p {} .reply a { padding: 5px 10px; background: #2d435a; -webkit-border-radius: 10px; border-radius: 10px; border: 1px solid #ccc; color:white; text-decoration:none; margin: 5px 0; } El resultado ser:

60

Claro que no se diferencian bien las respuestas del original. Pero como vimos antes el comentario tiene una clase de acuerdo a su nivel dentro de los comentarios anidados, basta con leer el cdigo HTML generado por esta pgina: <li class="comment byuser comment-author-admin bypostauthor odd alt depth-2 parent" id="comment-34"> Existen, entonces, varios niveles de profundidad (depth) en nuestros comentarios. Eliminemos el background de ol.comments li y colocamos las siguientes clases con diferentes tonos de gris por fondo: .depth-1 {background: #e1e1e1;} .depth-2 {background: #f1f1f1;} .depth-3 {background: #f9f9f9;} Y obtendremos: 61

Todo esto sin necesidad de generar en ningn momento la plantilla comentarios, utilizando slo el cdigo por defecto que WordPress genera. Para el caso de que queramos modificar drsticamente nuestra seccin de comentarios podemos generar un archivo comments.php o bien podemos hacerlo va hooks desde el functions.php. En este taller no vamos a ir mas all, ya que en SummArg constantemente sacamos notas con trucos para personalizar algunas plantillas de modo original. Pero a cambio les vamos a dejar de ejemplo el cdigo que estamos usando en nuestra plantilla para mostrar los comentarios por si les sirve de referencia. En nuestro functions.php colocamos la siguiente funcin para mostrar los comentarios con cdigo personalizado. <?php function mytheme_comment($comment, $args, $depth) { $GLOBALS['comment'] = $comment; ?> <li class="comment"> <div class="comment-top"> <?php echo get_avatar($comment,$size='36',$default='<path_to_url>' ); ?> <?php printf(__('<div class="fn">%s</div>'), get_comment_author_link()) ?> <?php if ($comment->comment_approved == '0') : ?> <em><?php _e('Tu comentario espera moderaci&oacute;n.') ?></em> <br /> <?php endif; ?>

<div class="comment-meta commentmetadata"> <br /> <a href="<?php echo htmlspecialchars( get_comment_link( $comment>comment_ID ) ) ?>"> <?php comment_date('j-n-y'); ?> </a><?php edit_comment_link(__('(Edit)'),' ','') ?></div> </div><!-- end of comment-top--> <div class="comment-text"> <?php comment_text() ?> <div class="reply"> <?php comment_reply_link(array_merge( $args, array('depth' => $depth, 'max_depth' => $args['max_depth']))) ?> </div> </div><!-- end of comment-text --> </li> <?php } Y el CSS .commentlist li.comment { width: 600px; display:block; margin: 5px auto; float:left; } .infos { width:565px; float:left; display:block; border-top: 1px double #ccc; padding: 5px; margin: 5px 0; font:normal 12px "tahoma", "arial", Sans-serif; color: #999; } .comment-top { background-color: #405e76; color: #fff; width:150px; float:left; border: 2px solid #405e76; padding: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 0px; -moz-border-radius-bottomright: 0px; -moz-border-radius-bottomleft: 5px; -webkit-border-radius: 5px 0px 0px 5px; border-radius: 5px 0px 0px 5px; } .comment-top a { color: #fff; }

62

.fn a, .fn{ font-size:12px; font-weight:bold; color: #fff; float:right; text-decoration: none; } .comment-text { background: url(images/comments-arrow.png) no-repeat; background-position: left top; border: 2px solid #405e76; background-color: #f1f1f1; width:407px; float:right; padding: 5px 5px 5px 20px; -moz-border-radius-topleft: 0px; -moz-border-radius-topright: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-bottomleft: 0px; -webkit-border-radius: 0px 5px 5px 0px; border-radius: 0px 5px 5px 0px; } La nica imagen que agregamos es comments-arrow.png, que no es mas que el tringulo que est al lado del cuadro azul con el avatar y el nombre del comentador. El resultado es el siguiente:

63

Esperamos que la clase de hoy les haya resultado esclarecedora. Como siempre, les dejamos el demo funcionando y los archivos de la clase para descargar. Clase 10

Clase 11: La plantilla de pgina


Las pginas en WordPress se utilizan para publicar contenido esttico, fuera del ordenamiento de las entradas, y soportan una estructura de pginas y subpginas, con un ilimitado nmero de hijos. Tambin soportan los templates personalizados que nos sirven para aplicar variaciones en el layout con muy pocas modificaciones a nuestras plantillas. Es importante saber que no aparecen en los feeds del sitio. En la clase 8 y la clase 8 anexo, dedicadas a las sidebars, jugamos un poco con la plantilla page. php y le dejamos la siguiente estructura.

64

Esa pgina es nuestra plantilla por defecto segn la ltima actualizacin al theme. Por eso vamos a aprender a agregar pginas personalizadas y veamos que opciones tenemos para ello. Por ltimo, vale la pena destacar que las plantillas de pginas soportan comentarios y si bien en esta clase no vamos a colocarlos, pueden seguir los mismos pasos que realizamos en la clase 10 para agregarlos.

Pginas personalizadas

Por un lado podemos optar por colocar desde el nombre del archivo la directiva para que se aplique la plantilla a una determinada pgina ya sea por su ID o por su slug.

page-{id}.php page-{slug}.php

De este modo, por ejemplo, si colocamos una plantilla con nombre page-10.php, WordPress intentar aplicar dicha plantilla automticamente a la pgina con ID 10. Lo negativo de este mtodo es que no permite aplicar una plantilla en particular a varias pginas de forma prctica, pero suele resultar bastante prctico para aplicar un estilo determinado a una nica pgina. Para crear una plantilla que luego se pueda aplicar a diferentes pginas segn le indiquemos desde el editor, primero debemos dar al archivo un nombre descriptivo. Nosotros vamos a crear una plantilla de pgina en donde el contenido abarcar 3/4 del layout y el restante lo usaremos para una sidebar. Tambin removeremos la sidebar horizontal, siendo nuestro objetivo lograr la siguiente estructura.

65

Primer paso: El archivo

Creamos un archivo llamado page-unasidebar.php. No es obligatorio colocar el prefijo page- en el nombre del archivo, simplemente lo hacemos para ser lo mas descriptivos posibles. Para evitar conflictos con el nombre, recuerden revisar el cuadro de Template Hierarchy y vern cuales son los nombres que WordPress se reserva para plantillas en particular. Colocamos en su encabezado el siguiente cdigo comentado dentro de llaves de php. <?php /* Template Name: Una Sidebar */ ?>

Segundo paso: El cdigo

La mayora del cdigo ya lo tenemos, podemos copiar el contenido anterior de page.php, eliminar las dos sidebars extras y modificar el ID del contenedor del texto de #wrapper-dos a #wrapper que ya tiene las medidas necesarias. <?php get_header(); ?> <div id=wrapper> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> <?php the_content(); ?> <?php the_time(F jS, Y) ?> | <?php the_author() ?> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de b&uacute;squedas.</p> <?php endif; ?> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?>

66

Tercer paso: Aplicar la plantilla a una pgina existente

Generar una plantilla por si misma no se refleja en ningn cambio en nuestro WordPress hasta que no asignamos la plantilla a una pgina existente. Para esto, nos dirigimos a nuestro panel de control y a una pgina existente le aadimos la plantilla. Guardamos la pgina al finalizar el cambio.

Pginas y subpginas

Como mencionamos al principio, las pginas pueden tener subpginas para ayudarnos a organizar mejor nuestra informacin. Para generar una subpgina, desde nuestro editor asignamos una pgina superior a nuestra pgina actual.

Guardamos y vamos a la seccin de Pginas en el escritorio. All observaremos como se refleja el sistema de jerarquas de pgina segn la pgina superior asignada en cada caso.

Por ltimo, en la seccin de Atributos de Pgina, cuando estamos en el editor de la pgina, podemos ver un casillero llamado Orden. El mismo soporta valores numricos para asignar un orden a las pginas que tengan la misma jerarqua. Ya que las pginas no se destacan por su orden cronolgico, como las entradas, es muy til poder asignar mediante este mtodo el orden en el que deseamos que se muestren nuestras pginas. 67

Mostrar las subpginas que tiene una pgina

La ubicacin mas utilizada para mostrar subpginas generalmente es en algn sitio de la sidebar, por lo que vamos a colocar un condicional para nuestra sidebar.php. En el mismo necesitamos comprobar si existen hijos de la pgina actual, caso contrario no debe mostrarse nada. Si el condicional resulta afirmativo (es una pgina y no una entrada o una categora, y adems resulta tener hijos), entonces se mostrar el ttulo Subpginas y desplegamos debajo el resultado de $children, en donde usamos la funcin wp_list_pages. El cdigo debe ir luego de abrir el div #sidebar. <?php $children = wp_list_pages('title_li=&child_of='.$post->ID.'&echo=0'); if ($children) { ?> <div class="widget"> <h3>Subp&aacute;ginas</h3> <ul class="subpages"> <?php echo $children; ?> </ul> </div> <?php } ?> Agregaremos un poco de estilo para que se muestre un poco mas prolijo. ul.subpages { margin:0; margin-left:10px; } .subpages li { list-style-type: circle; margin: 4px 0 4px 10px; text-indent:-5px; border-top: 1px solid #f9f9f9; padding: 2px 0 0 5px;; } ul.subpages li ul {

margin:0; } .subpages li a { text-decoration:none; } Realizamos un cambio en la plantilla de estilos en donde eliminamos los elementos #sidebar ul y #sidebar li, y creamos la clase .sidebarNews en nuestra lista de noticias en la Sidebar. <h3>Ultimas noticias</h3> <ul class="sidebarNews"> <?php query_posts('category_name=Blog&posts_per_page=4' ); while ( have_posts() ) : the_post(); ?> <li><a href="<?php echo get_permalink(); ?>"><?php the_title(); ?></a> <br /> Por <?php the_author(); ?></li> <?php endwhile; wp_reset_query(); ?> </ul> La nueva clase en el CSS. ul.sidebarNews { list-style-type:none; margin-bottom:20px; } ul.sidebarNews li { padding: 5px 10px; border-bottom: 1px solid #7b7b7b; color: #7b7b7b; } ul.sidebarNews li a{ text-decoration:none; color: #7b7b7b; } De ese modo podemos dar estilos diferentes a los listados que aparezcan dentro de la sidebar. Aadimos varios elementos hijos y nietos a la pgina con la que iniciamos las pruebas de esta clase y obtuvimos el siguiente resultado.

68

Pueden ver el ejercicio en funcionamiento en el demo online.

Plantillas de pgina con query_posts

Nada nos impide que usemos las plantillas de pgina para colocar consultas con query_posts, tal como vimos en la clase 5, y en esta oportunidad vamos a ver como crear una pgina en donde mostrar una categora de productos de un modo diferente al que usaremos luego en las plantillas

de categora. Primero generamos una categora llamada Productos. Antes de subir contenidos a dicha categora, vamos a establecer en el functions.php el tamao de la miniatura, para no tener que regenerarlas luego. add_image_size( producto, 195,195,true ); Subimos los artculos que necesitemos para ir probando nuestro theme y recordamos marcar como destacadas las imgenes que asignemos. Creamos un archivo llamado page-misproductos. php y en su interior colocaremos el cdigo que explicaremos por partes. Primero el encabezado del template. <?php /* Template Name: Mis productos */ get_header(); ?> Abrimos un contenedor con id #wrapper-full y colocamos el primer bucle, destinado a buscar el contenido de la pgina y tomar de l el ttulo y el contenido. Cerramos el bucle. <div id=wrapper-full> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h1><?php the_title(); ?></h1> <div class=descripcion><?php the_content(); ?></div> <?php endwhile; endif; Luego arrancamos con el bucle para mostrar los productos, en donde indicamos que queremos mostrar de a 8 productos y aadimos la variable de paginacin (leer ms sobre paginacin y query_posts aqu). El producto estar en un contenedor con la clase .producto y mostramos primero la imagen y luego el nombre del producto con su link. query_posts( array ( category_name => productos, showposts => 8, paged => get_query_var(paged) ) ); if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=producto> <?php the_post_thumbnail(producto); ?> <h2><a href=<?php the_permalink() ?> title=<?php the_title(); ?>><?php the_title(); ?></a></h2> </div> <?php endwhile; endif; ?> Finalmente colocamos los links de navegacin, cerramos el contenedor y llamamos al footer. <div class=navigation><?php posts_nav_link(,<p align=right>Siguientes</p>,<p align=left>Anteriores</p>); ?></ div>

69

</div><!-- end of wrapper-full --> <?php get_footer(); ?> Ahora vamos a darle un poco de estilo a la pgina. Primero definimos las propiedades que va a tener el contenedor de la pgina, que ocupa todo el ancho, el ttulo y la descripcin. #wrapper-full { width:920px; float:left; margin: 20px; } #wrapper-full h1 { text-align:center; padding: 20px 0 5px 0; border-bottom: 3px solid #7ec5ff; font-size:32px; } .descripcion p{ text-align:center; font-size:13px; line-height:18px; color: #7ec5ff; font-weight:bold; } .descripcion { margin: 0 0 10px 0; } Ahora daremos forma a los contenedores de producto aadiendo color de fondo, de bordes, sombras y un tamao especfico para el ttulo. .producto { float:left; width: 205px; height:225px; padding: 5px; margin: 6px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid /*#2d435a; #7ec5ff;*/ #e9e9e9; background-color: #f4f4f4; -webkit-box-shadow: 0px 0px 1px 1px #999; box-shadow: 0px 0px 1px 1px #999; } .producto img { border: 1px solid #b4b4b4; -webkit-border-radius: 5px; border-radius: 5px; } .producto h2 { font-size:14px; text-align:center; line-height:22px;

70

font-weight:bold; } .producto h2 a { color: #999; } Finalmente damos estilo a la paginacin para que aparezca siempre abajo. .navigation { width: 920px; margin:20px 0; height:20px; display:block; float:left; } El resultado ser el siguiente. 71

Encontrarn el ejercicio en nuestro demo online. Pueden descargar el theme completo desde aqu: themeTaller11

Clase 12: archive.php y plantillas por categora, fecha, autor, taxonoma, etiqueta.
Antes de arrancar con las plantillas de archivo en general, vamos a actualizar un poco el header. php de nuestro theme en funcin de adaptarlo a los requerimientos actuales con Facebook. Antes que nada, incluyamos un favicon, porque sino el theme se ve aburrido en nuestros navegadores. <link rel="shortcut icon" type="image/x-icon" href="<?php bloginfo('template_directory'); ?>/images/favicon.ico">

72

Acto seguido, vayamos colocando algunas etiquetas para que Facebook tome la informacin como nosotros queremos en cuanto al home, los interiores los dejaremos para que naturalmente tome los datos del cuerpo del contenido. <?php if (is_home() || is_front_page()) { ?> <meta property='og:locale' content='es_ES'/> <meta property='og:type' content='website'/> <meta property='og:title' content='themeTaller'/> <meta property='og:description' content='Un theme WordPress para aprender'/> <meta property='og:url' content='http://www.summarg.com/demos/themetaller/'/> <meta property='og:site_name' content='themeTaller'/> <meta property="og:image" content="<?php bloginfo('template_directory'); ?>/images/avatar.png"> <?php } ?> Por avatar.png debemos subir una imagen de mas de 350px x 350px. Para ver la informacin que Facebook toma de nuestras urls podemos usar la herramienta llamada Depurador.

Y constantamos en Facebook compartiendo el link en cuestin:

73

Listo! Ahora si, vamos a lo nuestro. Como ya vimos en la clase 4, la plantilla archive.php agrupa todos los listados de posts por: categoras, autor, fechas, etiquetas, custom post types archive y custom taxonomies. Esto significa que si solicitamos un listado de entradas de la categora con id 4 (miblog.com/?cat=4), WordPress primero buscar la plantilla para esa categora especfica, que sera category-4.php. Al no encontrarla, busca la plantillas de categoras en general, category.php. Si no existe, utiliza archive.php, si a su vez tampoco existe entonces buscar index.php. Lo mismo sucede para etiquetas, autor, fecha, y las dems. Existe una jerarqua que WordPress recorre en un orden especfico. Tomemos el caso de dos categoras de nuestra instalacin de prueba, la categora productos (id 111) y la categora blog (id 45). Podramos crearles una plantilla para cada uno generando el archivo category-productos.php y category-blog.php, respetando la primera forma que busca WordPress que es category-$slug.php. O bien podramos llamarlos caregory-111.php y el category-45. php, con el formato category-$id.php. Pero vamos a usar archive.php con Conditional Tags, slo por el placer de usar tantos condicionales. En un sitio normal con muchas visitas no nos conviene tener un archivo con tantos condicionales como lo vamos a crear ahora, y resulta mas efectivo crear tantos archivos como sea necesario. Pero estamos aprendiendo y esto es un gran experimento. Esto es lo que tenemos hasta ahora en nuestro archive.php: <?php get_header(); ?> <div id="wrapper"> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_excerpt(); ?> <?php the_time('F jS, Y') ?> | <?php the_author() ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de b&uacute;squedas.</p> <?php endif; ?>

</div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?> Vamos a tener dos objetivos simples. El primero es que cuando se muestre la categora de productos se vea tal como est en la pgina de productos, as que tomaremos gran parte del cdigo que est en la pgina personalizada que construimos la clase anterior. El header y el footer se mantienen, en todas las plantillas necesitamos de estos dos, as que vamos a manejarnos en el medio de ese espacio. Colocamos debajo de la llamada al header nuestro condicional con el correspondiente else. Cabe mencionar que necesitamos colocar un exit a cada if, ya que cuando se cumpla la condicin dada (ej. estamos en la categora 111) se va a mostrar ese cdigo y adicionalmente tambin se va a mostrar el que coloquemos dentro del else, ya que ambas condiciones se cumplen de algn modo. El exit corta o escapa a todo el conjunto una vez que una se cumple. <?php if (is_category(111)) { ?> <div id="wrapper-full"> <h1>Productos</h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="producto"> <?php the_post_thumbnail('producto'); ?> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> </div> <?php endwhile; endif; ?> <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div> </div><!-- end of wrapper-full --> <?php exit; } else { ?> Antes de la llamada al footer hay que colocar otra llave cerrando todo. <?php get_sidebar(); ?> <?php } ?> <?php get_footer(); ?> Cabe destacar que lo que tendramos que lograr es que no haya tantas aperturas y cierres de php, por lo que la lnea anterior bien la podramos convertir en esto: <?php get_sidebar(); } get_footer(); ?> Pero como dijimos antes, estamos aprendiendo y la intencin es que les resulte bien claro lo que vamos haciendo. Lo importante es que tengan presente que lo que ven ac es un pantallazo para entender como funciona el tema y de ah progresar. Ahora si vamos a nuestra categora de productos, podemos ver el listado de productos de la categora productos y de sus subcategoras, en el formato que escogimos. Podemos ver el resultado en el demo online. Pasemos a darle un formato diferente a las entradas en la categora blog para que quede del siguiente modo, sin barra lateral:

74

En la lnea superior a la del else, colocamos la nueva condicin y le daremos un formato distinto a nuestros contenedores. <?php } if (is_category(45)) { ?> <div id=wrapper-full> <h1>Blog</h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=blog> <a href=<?php the_permalink() ?> title=<?php the_title(); ?>> <h2><?php the_title(); ?></h2> <?php the_post_thumbnail(thumb); ?> <?php the_excerpt(); ?> </a> </div> <?php endwhile; endif; ?> <div class=navigation><?php posts_nav_link(,<p align=right>Siguientes</p>,<p align=left>Anteriores</p>); ?></ div> </div><!-- end of wrapper-full --> <?php exit; } else { ?> Y en el CSS definimos este nuevo contenedor para que tenga su propio estilo. .blog { width: 435px; height: 210px; float:left; margin: 5px; padding:5px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid #e9e9e9; background-color: #f4f4f4; } .blog a { text-decoration:none;

75

color: #333; } .blog img { float:left; margin: 5px 10px 0 0; border: 2px solid #e9e9e9; } .blog h2 { margin-top:5px; font-size:20px; line-height:24px; } .blog a h2 { text-decoration:none; color: #333; } .blog:hover { background-color: #ccc; } Podemos ver el resultado del ejercicio en esta ubicacin. Ahora hagamos una plantilla para mostrarse cuando el usuario solicite las entradas de un autor. Al igual que en el caso de las categoras, cuando se solicite el listado por autor, WordPress dar prioridad a la bsqueda de plantillas de la siguiente manera: 1. author-$nicename.php: En donde $nicename es el nombre de usuario del autor solicitado. 2. author-$id.php: En donde $id es el id de usuario del autor. 3. author.php: Plantilla genrica para todos los autores 4. archive.php: El nuestro! 5. index.php Vamos a usar nuevamente un condicional tag y a pensar en cmo queremos mostrar la pgina. Nuestro objetivo ser colocar arriba del listado (fuera del loop) la informacin que podamos sobre el autor solicitado. Y aqu tenemos un problema puesto que todas las funciones con get_the_author() y similares funcionan dentro del loop. Pero una de las maravillas de WordPress es su documentacin y la enorme comunidad que escribe sobre estos temas, as que le echamos una leda al snippet que public Kevin Muldon en WPHub y tomamos lo que necesitamos para construir nuestro recuadro de autor.

76

Luego del recuadro de autor (identificado con la class authorInfo) procedemos a colocar el bucle como siempre, con unos contenedores que esta vez contemplarn el espacio que necesita la sidebar para mostrarse. El cdigo PHP quedar de la siguiente manera: <?php } if (is_author()) { ?> <div id=wrapperUnTercio> <?php if(isset($_GET[author_name])) : $curauth = get_userdatabylogin($author_name); else : $curauth = get_userdata(intval($author)); endif; ?> <h1>Art&iacute;culos escritos por <?php echo $curauth->nickname; ?></ h1> <div class=authorInfo> <h2><?php echo $curauth->nickname; ?></h2> <p><strong>Sitio web</strong>: <a href=<?php echo $curauth->user_url; ?>><?php echo $curauth->user_url; ?></a></p> <p><strong>Sobre <?php echo $curauth->nickname; ?></strong>: <?php echo $curauth->user_description; ?></p> </div> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class=unTercio> <a href=<?php the_permalink() ?> title=<?php the_title(); ?>> <h2><?php the_title(); ?></h2> <?php the_post_thumbnail(thumb); ?> <?php the_excerpt(); ?> </a> </div> <?php endwhile; endif; ?> <div class=navigation><?php posts_nav_link(,<p align=right>Siguientes</p>,<p align=left>Anteriores</p>); ?></ div> </div><!-- end of wrapper --> <?php get_sidebar(); ?> <?php exit; } else { ?> El CSS para esta nueva seccin quedara de la siguiente manera: .authorInfo { width: 586px; padding: 10px; float:left; margin: 0 0 20px 20px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid #e9e9e9; background-color: #f4f4f4; } .authorInfo h2 { color: #7ec5ff; } .unTercio { width: 285px;

77

float:left; margin: 0 0 20px 20px; border-bottom:1px solid #e9e9e9; } .unTercio a { text-decoration:none; color: #333; } .unTercio img { float:left; margin: 5px 10px 0 0; border: 2px solid #e9e9e9; } .unTercio h2 { margin-top:5px; font-size:20px; line-height:24px; } .unTercio a h2 { text-decoration:none; color: #333; } .unTercio:hover { background-color: #f4f4f4; } Y el resultado puede verse en el siguiente ejemplo con un autor de nuestro demo. Finalmente vamos a construir una plantilla para tags (etiquetas) que sea prcticamente igual a la de autor con la diferencia de que queremos que se muestre la nube de etiquetas arriba de todo en un estilo que se adapte a nuestro trabajo.

78

El cdigo PHP deber utilizar el tag single_tag_title() para llamar al nombre del tag y utilizarlo en nuestro ttulo, luego colocamos la funcin wp_tag_cloud() sin parmetros para mostrar la nube de tags y el bucle sigue igual que en el de autor.

<?php } if (is_tag()) { ?> <div id="wrapperUnTercio"> <h1>Listado de art&iacute;culos con la etiqueta <?php single_tag_title(); ?></h1> <div class="tagCloud"> <?php wp_tag_cloud(); ?> </div> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="unTercio"> <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"> <h2><?php the_title(); ?></h2> <?php the_post_thumbnail('thumb'); ?> <?php the_excerpt(); ?> </a> </div> <?php endwhile; endif; ?> <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div> </div><!-- end of wrapper --> <?php get_sidebar(); ?> <?php exit; } else { ?> Para el CSS unicamente aadimos lo siguiente: .authorInfo, .tagCloud { width: 586px; padding: 10px; float:left; margin: 0 0 20px 20px; -webkit-border-radius: 5px; border-radius: 5px; border: 1px solid #e9e9e9; background-color: #f4f4f4; } .tagCloud a{ text-decoration:none; } Comprobamos que la nube y el listado se muestren correctamente en este link. Pueden descargar el theme desde aqu: themeTaller 12

79

Clase 13: Pgina de bsquedas e integracin con Google Custom Search Engine
Por defecto WordPress utiliza el template search.php para mostrar sus resultados de bsquedas, si no encuentra dicha plantilla entonces utiliza index.php. Vamos a colocar un pequeo formulario de bsqueda en el encabezado del sitio. Buscaremos lograr lo que se muestra en la siguiente imagen:

Para ello utilizaremos el siguiente cdigo que podremos despus del primer men: <div id="search"> <form method="get" id="searchform" action="<?php bloginfo('home'); ?>/"> <input type="text" value="Buscar..." onclick="this.value='';" name="s" id="s" class="searchtxt"/> <input name="" type="button" onclick="submit();" value="Buscar" class="btn" /> </form> </div> Para el estilo, primero aadiremos a #header un nuevo selector position:relative; #header { padding: 5px 20px; width:920px; height:110px; position:relative; } De este modo ahora todos los elementos que estn dentro de las etiquetas de #header pueden utilizar posicionamiento en relacin al padre. Procedemos a darle estilo a nuestro formulario. #search { width: 185px; border:1px solid #7ec5ff; position:absolute; right:20px; bottom:20px; -webkit-border-radius: 3px; border-radius: 3px; } #search form input#s { width:180px; height:20px; font-size:11px;

80

font-style:italic; padding: 0 0 0 5px; background-image:url(images/lupa.png); background-position:right center; background-repeat:no-repeat; border:none; } #search form input[type=button] { display:none; } Vern que nuestro #search utiliza el selector position y con el valor absolute nos permite definir un top y un right. Les recomiendo que lean la documentacin sobre positioning aqu y aqu. El archivo de lupa.png se encuentra dentro del nuevo paquete para descargar con la presente clase al pie de pgina. El botn necesitamos que exista, pero no necesitamos que se vea, por lo que le damos la indicacin para que no se muestre. Cuando el usuario ingrese su bsqueda y presione enter, la bsqueda se iniciar sin necesidad alguna de clickear un botn. WordPress buscar la plantilla search.php a la cual le colocaremos un layout estandar. <?php get_header(); ?> <div id="wrapper"> <h1>Resultados para <?php the_search_query(); ?></h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_excerpt(); ?> <?php the_time('F jS, Y') ?> | <?php the_author() ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de b&uacute;squedas.</p> <?php endif; ?> </div><!-- end of wrapper--> <div><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></div> <?php get_sidebar(); get_footer(); ?> Utilizamos la funcin the_search_query para mostrar en el ttulo el trmino de bsqueda que introdujo el usuario. Con esto ya nos queda la funcin de bsquedas de WordPress bastante completa.

81

Custom Search Engine de Google

Introduzcamos un formulario de bsquedas personalizadas de Google en nuestro theme. Las razones son varias: Posibilidad de monetizar nuestras bsquedas: Google CSE permite el uso de Google Adsense. Mejoras en el rendimiento del servidor al ahorrarnos las consultas a la base de datos. Permite buscar en varios sitios a definir por nosotros. Es de Google, necesitamos decir mas?

Para crear una cuenta para nuestro sitio nos dirigimos a www.google.com/cse, le damos nombre a nuestro buscador, definimos el idioma, los sitios en los que habr de buscar y activamos Adsense si lo deseamos. Lo que necesitamos de todo este proceso es la ID del motor de bsqueda generado.

82

Ahora bien, no queremos destruir el formulario de bsqueda que hemos agregado recientemente, as que aadiremos nuestro nuevo formulario en una de las sidebars. <div class="widget"> <form class="search" name="search" action="http://www.summarg.com/demos/themetaller/resultados.php" id="cse-search-box"> <input type="hidden" name="cx" value="010330468867836346028:q6pfqadll de" /> <input type="hidden" name="cof" value="FORID:11" /> <input type="hidden" name="ie" value="UTF-8" /> <input id="s" class="searchtxt" type="text" name="q" size="31" /> <input type="submit" name="sa" class="btn" /> </form> <script type="text/javascript" src="http://www.google.com/coop/cse/ brand?form=cse-search-box&lang=es"></script> </div> En el value del primer input debemos colocar el ID del motor de bsqueda que acabamos de generar. Emprolijamos un poco desde el style.css form#cse-search-box input#s { width: 220px; float:left; } form#cse-search-box input[type=submit] { float:left; border: 1px solid #7ec5ff; background-color: #7ec5ff; color: white;

height:22px; font-weight:bold; font-size:11px; margin: 0 0 0 5px; width:45px; overflow:hidden; } Comprobamos que se muestre correctamente en nuestro theme.

Ahora debemos colocar nuestra plantilla de resultados, que se llamar resultados.php. La misma contiene la estructura bsica de cualquier plantilla con la salvedad de que en vez de colocar un bucle slo colocaremos el script de Google CSE. Adems vamos a colocar este archivo fuera del directorio de nuestro theme, directamente en el raz del sitio, por lo que en la primer lnea utilizaremos una llamada para poder utilizar nuestro theme normalmente. resultados.php <?php require('./wp-blog-header.php'); ?> <?php get_header(); ?> <div id="wrapper"> <div id="cse-search-results"> <script type="text/javascript"> var googleSearchIframeName = "cse-search-results"; var googleSearchFormName = "cse-search-box"; var googleSearchFrameWidth = 600; var googleSearchDomain = "www.google.com"; var googleSearchPath = "/cse"; </script> <script type="text/javascript" src="http://www.google.com/afsonline/ show_afs_search.js"></script> </div> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?> Y efectuamos una bsqueda a modo de prueba.

83

Nuestro theme ya tiene dos formularios de bsqueda totalmente funcionales. Pods verlo en nuestro demo online. Descarg la clase: themeTaller 13

84

Clase 14: Paginacin, breadcrumbs y pgina de error 404.php


Esta clase podra considerarse la ltima en lo que a detalles para construir un theme completo y funcional respecta. La paginacin, los breadcrumbs (camino de migajas) y la pgina de error dan la terminacin justa a nuestro proyecto. Claro que nos quedan cinco clases mas en donde abordaremos temas mas complejos, como los custom post types y la instalacin de un framework que nos permita insertar opciones a nuestro theme. Por favor chequeen el temario y si consideran que qued fuera algn tema importante, hganlo saber mediante un comentario o un mensaje privado desde nuestro formulario de contacto. Comenzaremos reemplazando la paginacin por defecto que WordPress nos ofrece (que consiste en links de anterior y siguiente) y colocaremos algo mas vistoso.

Actualmente el plugin mas utilizado para lograr esto es wp-pagenavi, pero en esta oportunidad insertaremos una paginacin sin utilizar ningn plugin. Meramente creamos la funcin y la insertamos en nuestro functions.php function wp_pagenavi() { global $wp_query, $wp_rewrite; $pages = ''; $max = $wp_query->max_num_pages; if (!$current = get_query_var('paged')) $current = 1; $args['base'] = str_replace(999999999, '%#%', get_pagenum_ link(999999999)); $args['total'] = $max; $args['current'] = $current; $total = 1; $args['mid_size'] = 3; $args['end_size'] = 1; $args['prev_text'] = '<img src="'.get_bloginfo('template_url').'/images/arrow-left.png" />'; $args['next_text'] = '<img src="'.get_bloginfo('template_url').'/images/arrow-right.png" />'; if ($max > 1) echo '<div class="wp-pagenavi">'; if ($total == 1 && $max > 1) $pages = '<span class="pages">P&aacute;gina ' . $current . ' de ' . $max . '</span>'; echo $pages . paginate_links($args); if ($max > 1) echo '</div>'; } Las dos imgenes que mencionamos en los argumentos se entregan en el RAR que pueden descargar al pi del tutorial. La funcin lo que hace es obtener las cantidades mximas de pginas existentes en la query y darle un formato que contenga mas informacin y nos permita navegar salteando pginas si lo deseamos. Ahora abrimos nuestro archive.php y reemplazamos estas lneas: <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div>

85

Por esta: <div class="navigation"><?php wp_pagenavi(); ?></div> Este reemplazo lo debemos ejecutar 5 veces en total. Luego continuamos con el estilo, en nuestro CSS colocamos: .wp-pagenavi span.pages, .wp-pagenavi a.page, .wp-pagenavi .page-numbers, .wp-pagenavi span.extend, .wp-pagenavi a.first, .wp-pagenavi a.nextpostslink, .wp-pagenavi a.previouspostslink, .wp-pagenavi a.last { padding:5px; height:20px; margin-right:5px; background: #7ec5ff; color:white; border:1px solid #5995c6; text-decoration:none; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; display:block; float:left; } .wp-pagenavi span.current, .wp-pagenavi a:hover { padding:5px; height:20px; margin-right:5px; background:#fff; color:#7ec5ff; border:1px solid #5995c6; text-decoration:none; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; display:block; float:left; } .wp-pagenavi a.next, .wp-pagenavi a.prev { padding-top:1px 0; height:20px; margin-right:5px; background: #7ec5ff; color:white; border:1px solid #5995c6; text-decoration:none; border-radius: 3px;

86

-moz-border-radius: 3px; -webkit-border-radius: 3px; display:block; float:left; } .wp-pagenavi img { height:20px; width:25px; margin-top:0px; } Y con ello bastar.

Breadcrumbs, migajas de pan


87 El breadcrumb es til para permitirle al usuario volver a una instancia anterior dentro de un rbol de categoras, o para saber en donde est y su relacin con el inicio. Existen varios plugins para insertar breadcrumbs que ya vienen con estilos y son muy bonitos, pero nosotros crearemos la funcin en nuestro functions.php, ya que esto nos dar la oportunidad de personalizarlo si lo deseamos. Bsicamente lo que hace la funcin es preguntarse en donde se encuentra mediante conditional tags y en base a ello muestra diferentes funciones, ya sea el ttulo, el rbol de categoras, la fecha, etc. /*Breadcrumbs*/ function the_breadcrumbs() { echo '<p>'; if (!is_front_page()) { echo '<a href="'; echo get_option('home'); echo '">'; echo 'Inicio'; echo "</a> &raquo; "; if (is_category() || is_single()) { the_category(' &raquo; '); if (is_single()) { echo the_title(); } } elseif (is_page()) { echo the_title(); } elseif (is_tag()) { single_tag_title(); } elseif (is_day()) { echo "Archivo de "; the_time('F jS, Y');} elseif (is_month()) { echo "Archivo de "; the_time('F, Y'); } elseif (is_year()) { echo "Archivo de "; the_time('Y'); } elseif (is_author()) { echo "Archivo de Autor"; } elseif (isset($_GET['paged']) && !empty($_GET['paged'])) { echo "Archivo"; } elseif (is_search()) { echo "Resultados de b&uacute;squeda";} elseif (is_404()) { echo "Error 404";} }else{ echo '<a href="'; echo get_option('home');

'</p>'; } /*End of Breadcrumbs*/ Aadimos un estilo muy bsico. .breadcrumb { width: 100%; float:left; display:block; } .breadcrumb p a { text-decoration:none; } .breadcrumb p { font-size:12px; } E insertamos la funcin en archive.php debajo del div id#wrapper y debajo de cada apertura de un div contenedor de modo de atender todos los condicionales: <div class="breadcrumb"><?php the_breadcrumbs(); ?></div> Es un cdigo muy sencillo y no es del todo completo, pero sirve a nuestros propsitos. La funcin puede insertarse en la plantilla single.php, page.php, search.php, incluso en el home aunque no parece necesario. Es a criterio del desarrollador. Finalmente necesitamos elaborar una pgina de error 404. Esta pgina se visualiza cuando el usuario solicita una URL inexistente, ya sea porque se cambi la URL adrede, o bien se borr dicha entrada, o cualquier otro motivo. La plantilla que debemos crear es: 404.php <?php get_header(); ?> <div id="wrapper"> <h2>Error 404</h2> <p>Lo sentimos, el contenido que est&aacute; intentando visualizar no se encuentra o fue movido a otra parte. Por favor utilice nuestro formulario de b&uacute;squedas</p> <div id="searchInner"> <form method="get" id="searchform" action="<?php bloginfo('home'); ?>/"> <input type="text" value="Buscar..." onclick="this.value='';" name="s" id="q" class="searchtxt"/> <input name="" type="button" onclick="submit();" value="Buscar" class="btn" /> </form> </div> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?>

echo echo echo } echo

'">'; 'Inicio'; "</a>";

88

El formulario es el mismo que el del header, pero debemos cambiar leves detalles (por ejemplo, cambiar el posicionamiento absoluto a un float) y adems no podemos usar un id dos veces, as que lo reemplazamos. #searchInner { width: 185px; border:1px solid #7ec5ff; float:left; -webkit-border-radius: 3px; border-radius: 3px; } #searchInner form input#q { width:180px; height:20px; font-size:11px; font-style:italic; padding: 0 0 0 5px; background-image:url(images/lupa.png); background-position:right center; background-repeat:no-repeat; border:none; } #searchInner form input[type=button] { display:none; } Si ingresamos una url cualquiera (ej. http://www.summarg.com/demos/themetaller/asdasdasd) Obtendremos el siguiente resultado:

89

Si googlean imgenes de error 404 van a encontrar ideas muy divertidas y originales para utilizar en este tipo de pginas. Pueden descargar la clase de hoy desde aqu: themeTaller 14

Clase 15: Framework para opciones administrativas e insercin de anuncios

Nuestro theme ya est listo, pero cmo podemos hacernos la vida mas simple a la hora de gestionar los anuncios de un sitio? Sabemos que colocar anuncios Adsense ac y all es cosa de una vez, pero el asunto se vuelve mas complejo si adems vendemos espacios de forma mensual y nuestros anunciantes cambian con frecuencia. Vamos a retomar una herramienta que les presentamos hace tiempo, que es gratuita y se integra a nuestro theme muy bien: Options Framework Theme de WP Theming (tiene una versin paga con varias herramientas muy interesantes). Esta herramienta, que podemos descargar desde github, nos permite usar variables personalizadas en situaciones diferentes de las que vamos a plantear en esta clase. Pensemos que nos puede permitir ingresar el cdigo hexadecimal de un nuevo color de fondo, o texto para incluir en un rea en donde no queremos usar widgets, trozos de cdigo completos, mensajes globales a usuarios, etc. Lo primero que necesitamos hacer es descomprimir el paquete y colocar el siguiente cdigo al inicio de nuestro functions.php, despus de la etiqueta <?php. if ( ! function_exists( optionsframework_init ) ) { define( OPTIONS_FRAMEWORK_DIRECTORY, get_template_directory_uri() . / inc/ ); require_once dirname( __FILE__ ) . /inc/options-framework.php; } Luego copiamos el archivo options.php y la carpeta /inc/ y las colocamos en el raz de nuestro theme. 90

Ahora editemos el archivo options.php, que es en donde podremos gestionar las pestaas y sus contenidos dentro de Theme Options.

Para eliminar el contenido de pruebas debemos borrar desde la lnea 105 del options.php hasta la 288. Vamos a buscar aadir dos sectores de publicidad a los que le aadiremos una imagen y su respectivo link, y aprovechamos a completar los tres cuadros de texto que figuran debajo del slider desde las opciones de nuestro theme. 91

Vamos a trabajar insertando las opciones a partir de la lnea 105. Primero generamos el encabezado de nuestra seccin Publicidad. $options[] = array( 'name' => __('Publicidad', 'options_framework_theme'), 'type' => 'heading'); Luego aadimos dos campos de texto que vamos a usar para colocar los links, y dos campos de upload para las imgenes. $options[] = array( 'name' => __('Link Ad Header', 'options_framework_theme'), 'desc' => __('Link conteniendo http://...', 'options_framework_theme'), 'id' => 'link_ad_header', 'type' => 'text'); $options[] = array( 'name' => __('Imagen Ad Header', 'options_framework_theme'), 'desc' => __('400x60px', 'options_framework_theme'), 'id' => 'image_ad_header', 'type' => 'upload'); $options[] = array( 'name' => __('Link Ad Footer', 'options_framework_theme'), 'desc' => __('Link conteniendo http://...', 'options_framework_theme'), 'id' => 'link_ad_footer', 'std' => 'Default', 'type' => 'text'); $options[] = array( 'name' => __('Imagen Ad Footer', 'options_framework_theme'), 'desc' => __('281x100px', 'options_framework_theme'), 'id' => 'image_ad_footer', 'type' => 'upload'); El parmetro name especifica el ttulo de nuestro campo, desc sirve para colocar una descripcin que se ver debajo del ttulo, id se utiliza luego para invocar al contenido del elemento, type define el tipo de campo que ser. Tambin tenemos adicionalmente class (para elegir algunas variantes de type) y std que sirve para colocar contenido por defecto.

92

Abrimos nuestro header.php y colocamos el siguiente cdigo luego del div#logo: <?php if ( of_get_option( 'image_ad_header' ) ) { ?> <div class="adHeader"> <a href="<?php echo of_get_option( 'link_ad_header', 'no entry' ); ?>"> <img src="<?php echo of_get_option( 'image_ad_header' ); ?>" /> </a> </div> <?php } ?> Con ello establecemos un condicional en el que si encuentra que #image_ad_header (nuestro id de la imagen para el header) tiene contenido, entonces coloca un div.adHeader y en su interior el link con el contenido de #link_ad_header y la imagen del id ya mencionado. Le damos un poco de estilo a la clase que acabamos de crear. .adHeader { width: 400px; height:60px; float:left; margin: 35px 0 0 10px; } Subimos contenido para estos dos campos.

93

Y confirmamos que se vea como lo deseamos.

Excelente! Ahora procedemos a repetir la operacin pero esta vez en el footer. Aprovechamos a comentar que la clase .widget en el footer debera tener 293px de ancho, as que lo corregimos, del mismo modo la imagen del aviso deber tener ese valor para su ancho. Podemos usar dicha clase para colocar dentro nuestra imagen en caso de que exista.

<?php if ( of_get_option( 'image_ad_footer' ) ) { ?> <div class="widget"> <a href="<?php echo of_get_option( 'link_ad_footer', 'no entry' ); ?>"> <img src="<?php echo of_get_option( 'image_ad_footer' ); ?>" /> </a> </div> <?php } ?> Finalmente vamos a nuestra seccin de destacados. Hasta ahora lo venamos manejando con publicaciones en la categora Productos Destacados, pero dado el formato que necesitamos queda algo desprolijo y se nos ocurre que podramos mejorarlo de este modo. Adems suponemos que puede haber muchsimas entradas y que cuando el dueo del sitio decida modificar los destacados puede cometer varios errores, como excederse en la cantidad de texto o colocar una imagen dentro, y eso rompera nuestro home. Este es el cdigo que tenemos ahora. <div id="featured"> <?php query_posts('category_name=Producto Destacado&posts_per_page=3' ); while ( have_posts() ) : the_post(); ?> <div class="item"> <h3><?php the_title(); ?></h3> <?php the_content(); ?> </div><!-- end of item" --> <?php endwhile; wp_reset_query(); ?> </div><!-- end of featured --> Vamos a crear en options.php tres campos para cada uno de los destacados, uno para el ttulo, otro para el texto y uno mas para el link. Nos quedarn un total de nueve campos. Les mostramos los primeros tres junto con el separador para que todo esto est en una pestaa a la que llamaremos Destacados. $options[] = array( 'name' => __('Destacados', 'options_framework_theme'), 'type' => 'heading'); $options[] = array( 'name' => __('Titulo destacado 1', 'options_framework_theme'), 'id' => 'titulo_destacado_1', 'std' => 'Default Value', 'type' => 'text'); $options[] = array( 'name' => __('Link destacado 1', 'options_framework_theme'), 'id' => 'link_destacado_1', 'type' => 'text'); $options[] = array( 'name' => __('Texto destacado 1', 'options_framework_theme'), 'id' => 'textarea_destacado_1', 'type' => 'textarea'); Y en el index.php reemplazamos el bucle que llama a los tres elementos por: <div class="item"> <h3><?php echo of_get_option( 'titulo_destacado_1' ); ?></h3> <a href="<?php echo of_get_option( 'link_destacado_1' ); ?>"> 94

<p><?php echo of_get_option( 'textarea_destacado_1' ); ?></p> </a> </div><!-- end of item --> <div class="item"> <h3><?php echo of_get_option( 'titulo_destacado_2' ); ?></h3> <a href="<?php echo of_get_option( 'link_destacado_2' ); ?>"> <p><?php echo of_get_option( 'textarea_destacado_2' ); ?></p> </a> </div><!-- end of item --> <div class="item"> <h3><?php echo of_get_option( 'titulo_destacado_3' ); ?></h3> <a href="<?php echo of_get_option( 'link_destacado_3' ); ?>"> <p><?php echo of_get_option( 'textarea_destacado_3' ); ?></p> </a> </div><!-- end of item --> Los links que aadimos van a generar un subrayado que no vamos a querer, as que lo eliminamos va CSS y de paso le cambiamos el color de fondo a cada elemento cuando se le hace un hover. .item a { text-decoration:none; } .item:hover { background-color:#f4f4f4; } 95

Nuestro panel va a quedar con dos pestaas ahora:

Podemos ver el resutado en nuestro demo, y descargar la clase de hoy themeTaller 15. Antes de finalizar queremos destacar que el framework que elegimos contiene las siguientes opciones de campos para incluir: Campos de texto (pequeos, medianos, largos) Textarea con el editor Upload de archivos Radio buttons Checkboxes Selects Select con las pginas de WordPress Select con las categoras de WordPress Select con las etiquetas de WordPress Color picker Selector de imgenes precargadas Todas estas opciones nos dan mucho margen de trabajo para hacer un theme amigable y completo. Adems de ser fcil de entender, es muy liviano y cuenta con la posibilidad de comprar la licencia para extender sus funciones.

96

Clase 16: Custom Post Types: Portfolio y plantilla single-cpt.php.


En esta clase y en las dos siguientes vamos a intentar tocar los aspectos mas relevantes a los Custom Post Types, con los que daremos vida a un portfolio que puede serles de utilidad para exhibir toda clase de productos, pelculas, libros, etc. Los Custom Post Types son la mxima expresin de contenido personalizado dentro de WordPress, podemos hacer que se comporten como posts o pginas, que usen categoras, taxonomas, etiquetas, todas o ninguna. Tienen su propio lugar en nuestro escritorio de la plataforma y nos dan una amplia flexibilidad a la hora de crear contenidos. Tambin, vale aclarar, nos permite separar estos contenidos de las pginas y las entradas comunes. Pueden comenzar a leer sobre este tema en el codex de WordPress en este link. Nosotros iremos directo al grano y para ello lo primero que vamos a hacer es definir el tipo de contenido Portfolio desde el functions.php. add_action( 'init', 'register_cpt_portfolio' ); function register_cpt_portfolio() { $labels = array( 'name' => _x( 'Portfolio', 'portfolio' ), 'singular_name' => _x( 'Portfolio', 'portfolio' ), 'add_new' => _x( 'Agregar', 'portfolio' ), 'add_new_item' => _x( 'Agregar trabajo', 'portfolio' ), 'edit_item' => _x( 'Editar trabajo', 'portfolio' ), 'new_item' => _x( 'Nuevo trabajo', 'portfolio' ), 'view_item' => _x( 'Ver trabajo', 'portfolio' ), 'search_items' => _x( 'Buscar en Porfolio', 'portfolio' ), 'not_found' => _x( 'No se encontraron trabajos', 'portfolio' ), 'not_found_in_trash' => _x( 'No se encontraron en la papelera', 'portfolio' ), 'parent_item_colon' => _x( 'Parent Portfolio:', 'portfolio' ), 'menu_name' => _x( 'Portfolio', 'portfolio' ), ); $args = array( 'labels' => $labels, 'hierarchical' => false, 'description' => 'Trabajos que realizamos recientemente', 'supports' => array( 'title', 'editor', 'thumbnail', 'customfields' ), 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => true, 'publicly_queryable' => true, 'exclude_from_search' => false, 'has_archive' => true, 'query_var' => true, 'can_export' => true, 'rewrite' => true, 'capability_type' => 'post' ); } register_post_type( 'portfolio', $args );

97

Mediante este cdigo registramos el post type asignndole todos los valores necesarios para que se conviertan en un tipo de entradas que acepta archivo, que se muestra en los menes, que se puede exportar, que soporta los campos de ttulo, el editor, miniaturas y custom fields, etc. Existe un generador de cdigo muy bueno que elabor la gente de themergency.com en este link. Al completar el formulario en varios pasos obtenemos el cdigo resultante de nuestras especificaciones. Vamos a querer asignarle categoras a nuestras entradas, y queremos definir las mismas de modo independiente al resto de las entradas comunes, as que para ello seguimos colocando cdigo en nuestro functions.php: function register_portfoliotaxonomies() { $labels = array( 'name' => _x( 'tipos', 'taxonomy general name' ), 'singular_name' => _x( 'tipo', 'taxonomy singular name' ), 'add_new' => _x( 'Agregar tipo', 'tipo'), 'add_new_item' => __( 'Agregar tipo' ), 'edit_item' => __( 'Editar tipo' ), 'new_item' => __( 'Nuevo tipo' ), 'view_item' => __( 'Ver tipo' ), 'search_items' => __( 'Buscar tipos' ), 'not_found' => __( 'No encontrado' ), 'not_found_in_trash' => __( 'No encotrado' ), ); $pages = array('portfolio'); $args = array( 'labels' => $labels, 'singular_label' => __('tipo'), 'public' => true, 'show_ui' => true, 'hierarchical' => true, 'show_tagcloud' => false, 'show_in_nav_menus' => true, '_builtin' => false, 'rewrite' => array('slug' => 'porfoliotax','with_ front' => FALSE ), ); register_taxonomy('portfoliotaxonomies', $pages, $args); } add_action('init', 'register_portfoliotaxonomies'); De este modo generamos las categoras para Portfolio. Pueden revisar una descripcin de los parmetros de register_taxonomy en el codex. Procedemos a completar con algunas categoras antes de subir material. Necesitamos tener algunas entradas ingresadas para poder trabajar, as que vamos a crear un portfolio de una empresa de marketing y diseo.

98

Ahora si podemos proceder a agregar algunas entradas en diferentes categoras. A medida que lo hagamos veremos que tenemos problemas para visualizar los contenidos (salvo que no estn usando URLs amigables), por lo que debemos recrear los permalinks. El modo mas sencillo es cambiando la configuracin un momento a predeterminado y volvindola a cambiar a la que hayamos elegido.

99

Metabox: Los custom fields de forma fcil

Vamos a echar mano a un recurso muy til en esa nueva seccin: los metaboxes. Estas cajas son una versin sofisticada para manejar los valores de custom fields, dejando al usuario un entorno mas amigable para completar los campos. Vamos a crear tres campos de texto y un campo con dos radio buttons. Los datos que recabemos con los tres primeros elementos sern usados en clases por venir, pero los radio los vamos a usar hoy mismo.

Functions.php /* Metabox */ $meta_box = array( 'id' => 'metabox-portfolio', 'title' => 'Elementos del Portfolio', 'page' => 'portfolio',

'context' => 'normal', 'priority' => 'high', 'fields' => array( array( 'name' => 'Cliente', 'desc' => 'Nombre del cliente', 'id' => 'cliente', 'type' => 'text', 'std' => 'Un Cliente' ), array( 'name' => 'Socios', 'desc' => 'Nombre del/los socios', 'id' => 'socios', 'type' => 'text', 'std' => '' ), array( 'name' => 'Descripcion', 'desc' => 'Descripcion corta para la portada', 'id' => 'descripcion', 'type' => 'text', 'std' => '' ), array( 'name' => 'Layout', 'id' => 'layout', 'type' => 'radio', 'options' => array( array('name' => 'Layout1', 'value' => 'Layout1'), array('name' => 'Layout2', 'value' => 'Layout2') ) ) ) ); add_action('admin_menu', 'mytheme_add_box'); // Add meta box function mytheme_add_box() { global $meta_box; add_meta_box($meta_box['id'], $meta_box['title'], 'mytheme_show_box', $meta_box['page'], $meta_box['context'], $meta_box['priority']); } // Callback function to show fields in meta box function mytheme_show_box() { global $meta_box, $post; // Use nonce for verification echo '<input type="hidden" name="mytheme_meta_box_nonce" value="', wp_ create_nonce(basename(__FILE__)), '" />'; echo '<table class="form-table">'; foreach ($meta_box['fields'] as $field) {

100

// get current post meta data $meta = get_post_meta($post->ID, $field['id'], true); echo '<tr>', '<th style="width:20%"><label for="', $field['id'], '">', $field['name'], '</label></th>', '<td>'; switch ($field['type']) { case 'text': echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:97%" />', '<br />', $field['desc']; break; case 'textarea': echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="4" style="width:97%">', $meta ? $meta : $field['std'], '</textarea>', '<br />', $field['desc']; break; case 'select': echo '<select name="', $field['id'], '" id="', $field['id'], '">'; foreach ($field['options'] as $option) { echo '<option', $meta == $option ? ' selected="selected"' : '', '>', $option, '</option>'; } echo '</select>'; break; case 'radio': foreach ($field['options'] as $option) { echo '<input type="radio" name="', $field['id'], '" value="', $option['value'], '"', $meta == $option['value'] ? ' checked="checked"' : '', ' />', $option['name']; } break; case 'checkbox': echo '<input type="checkbox" name="', $field['id'], '" id="', $field['id'], '"', $meta ? ' checked="checked"' : '', ' />'; break; } echo '<td>', '</tr>'; } } add_action('save_post', 'mytheme_save_data'); // Save data from meta box function mytheme_save_data($post_id) { global $meta_box; // verify nonce if (!wp_verify_nonce($_POST['mytheme_meta_box_nonce'], basename(__ echo '</table>';

101

FILE__))) { return $post_id; } // check autosave if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; } // check permissions if ('page' == $_POST['post_type']) { if (!current_user_can('edit_page', $post_id)) { return $post_id; } } elseif (!current_user_can('edit_post', $post_id)) { return $post_id; } foreach ($meta_box['fields'] as $field) { $old = get_post_meta($post_id, $field['id'], true); $new = $_POST[$field['id']]; if ($new && $new != $old) { update_post_meta($post_id, $field['id'], $new); } elseif ('' == $new && $old) { delete_post_meta($post_id, $field['id'], $old); } } 102

Esos radio buttons los vamos a usar para crear dos estilos diferentes de archivo single para nuestro custom post type.

La plantilla single-cpt.php

Arranquemos a generar la plantilla para visualizar un elemento. Recordemos lo referente a jerarquas de plantillas (template hierarchy) y segn el mapa de plantillas necesitamos crear un archivo single-portfolio.php. Vamos a crear tres plantillas en una usando condicionales en base a ese campo Layout. La primera de ellas contendr un cuadro con los datos del metabox arriba de todo, y en la barra lateral lista entradas de la misma categora.

Veamos la primera parte de nuestro cdigo en single-portfolio.php. La estructura de colocar al inicio un get_header() seguido de un div que haga de contenedor es igual en todas. Lo que nosotros necesitamos es inmediatamente obtener el valor del custom field layout por lo que primero llamamos a la variable global $post y luego procedemos a usar get_post_meta. Construimos un contenedor con los valores de cliente, socios y descripcin, a la que le colocamos una miniatura a la izquierda (para obtener la miniatura pequea por defecto de WordPress usamos thumb). Seguidamente, y siempre dentro del bucle, colocamos las funciones para llamar al ttulo y al contenido. <?php get_header(); ?> <div class="wrapperPortfolio"> <?php global $post; $layout = get_post_meta(get_the_id(), 'layout', TRUE); if ($layout == 'Layout1') { if ( have_posts() ) : while ( have_posts() ) : the_post(); $cliente = get_post_meta(get_the_id(), 'cliente', TRUE); $socios = get_post_meta(get_the_id(), 'socios', TRUE); $descripcion = get_post_meta(get_the_id(), 'descripcion', TRUE); ?> <div class="portfolioUno"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <div class="portfolioDetalle"> <?php the_post_thumbnail('thumb'); ?> <?php echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; echo '<br /><div class="detalleTitulo">Socios</div> '.$socios; echo '<br /><div class="detalleTitulo">Decripcion</div> '.$descripcion.'</p>'?> </div> <?php the_content(); ?> </div><!-- end of portfolioUno --> <?php endwhile; endif; ?> En la segunda parte de nuestro Layout1 queremos encargarnos de colocar en la barra lateral otras entradas de la misma categora. Esto ya resulta fcil para nosotros, no es cierto? De paso dejo establecidos los condicionales para los otros Layouts, por el momento no se ver nada mas que un texto. <div class="sidebarPortfolio"> <div class="itemPortfolio"> <h3>Otros trabajos relacionados</h3> </div> <?php $categories = get_the_category($post->ID); $args= array( 'cat' => $categories, 'posts_per_page' => 4, 'post_type' => 'Portfolio' ); query_posts($args); if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

103

<div class="itemPortfolio"> <?php the_post_thumbnail('portfolio'); ?> <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3> </div> <?php endwhile; endif; ?> </div> <?php } else if ($layout == 'Layout2') { ?> Otro Layout <?php } else { ?> Y otro layout mas.... <?php } ?> </div><!-- end of wrapper--> <?php get_footer(); ?> Necesitamos definir el tamao de la imagen destacada, colocamos el siguiente valor en nuestro functions.php: add_image_size( 'portfolio', 230,130, true ); Y hasta aqu nuestro CSS. .wrapperPortfolio { width: 940px; float:left; margin: 20px 0 20px 20px; } .portfolioUno { width: 670px; float:left; } .sidebarPortfolio { width: 230px; margin: 20px 0 0 20px; float:left; } .itemPortfolio { width: 230px; border:1px solid #7ec5ff; float:left; display:block; margin: 0 0 20px 0; background-color:#7ec5ff; } .itemPortfolio img { margin:0; padding:0; } .itemPortfolio h3 { font-size:16px; line-height:22px; font-weight:bold; text-align:center; 104

margin: 5px 0 0 0; color:white; } .itemPortfolio h3 a { color:white; text-decoration:none; } .portfolioDetalle { width: 650px; padding:10px; margin: 0 0 20px 0; background-color: #f4f4f4; -webkit-border-radius: 5px; border-radius: 5px; display:block; float:left; } .portfolioDetalle img { float:left; margin: 0 10px 0 0; } .detalleTitulo { width: 85px; color: #7ec5ff; font-weight:bold; float:left; text-align:right; margin: 0 5px 0 0; } En Layout 2 vamos a disponer de los elementos de un modo ligeramente diferente, construyendo en nuestra barra lateral el rea en donde mostraremos los datos del metabox y debajo nuestra imagen destacada. Aadimos al functions.php el nuevo tamao que usaremos para the_post_ thumbnail();. Insertamos el siguiente valor debajo del ltimo add_image_size(); add_image_size( 'layout2', 340, 300, true); As quedar nuestro Layout 2:

105

Ahora procedemos a completar el single-php.php reemplazando ese texto que colocamos previamente Otro Layout. if ( have_posts() ) : while ( have_posts() ) : the_post(); $cliente = get_post_meta(get_the_id(), 'cliente', TRUE); $socios = get_post_meta(get_the_id(), 'socios', TRUE); $descripcion = get_post_meta(get_the_id(), 'descripcion', TRUE); ?> <div class="portfolioDos"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_content(); ?> </div><!-- end of portfolioDos --> <div class="sidebarPortfolioDos"> <div class="portfolioDosDetalle"> <?php echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; echo '<br /><div class="detalleTitulo">Socios</div> '.$socios; echo '<br /><div class="detalleTitulo">Decripcion</div> '.$descripcion.'</p>'?> </div> <?php the_post_thumbnail('layout2'); ?> </div> <?php endwhile; endif; ?> Este segundo layout es mas sencillo pues tiene un solo bucle. Veamos el CSS: .portfolioDos { width: 560px; float:left; } .portfolioDosDetalle { width:320px; padding:10px; margin: 0 0 20px 0px; background-color: #f4f4f4; -webkit-border-radius: 5px; border-radius: 5px; display:block; float:right; } .sidebarPortfolioDos { width: 340px; margin: 20px 0 0 10px; padding: 0 0 0 10px; border-left: 1px solid #f4f4f4; float:left; } Para el tercer Layout, puesto que ya comprendimos la idea, vamos a insertar parte de la plantilla single.php con la salvedad de que tenemos que eliminar un contenedor y vamos a eliminar el area de informacin de la entrada.

106

if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_content(); ?> </div><!-- end of dos-tercios --> <?php endwhile; endif; get_sidebar(); Con esto terminamos por hoy, esperamos que hayan comprendido la idea de la plantilla singlecpt.php y que puedan explotarla al mximo a la hora de disear sus sitios. Demo online Layout 1 | Demo online Layout 2 | Demo online Layout 3 Descargar la clase de hoy: themeTaller 16 Nota importante: Para generar los metabox nosotros utilizamos un framework que encontramos hace un tiempo en la web y no recordamos quin es su autor, por eso se los dejamos para que lo utilicen aqu: meta-box Si alguno reconoce el cdigo y al autor, por favor envenos un mensaje para mencionarlo como corresponde.

107

Clase 17: Custom Post Types: Portfolio y plantilla de taxonomas.


En esta clase vamos a encarar la plantilla de taxonomas y, de yapa, vamos a construir una pgina para ver todo el portfolio de un modo un poco mas interesante. Volviendo, como siempre, a la jerarqua de plantillas, vemos que el formato de archivo que tenemos que usar para poder visualizar nuestros elementos por tipo es taxonomy-$taxonomy.php. Entonces daremos a nuestro archivo el nombre de taxonomy-portfoliotaxonomies.php, ya que as lo llamamos en el archivo functions.php. <?php get_header(); ?> <div class="wrapperPortfolio"> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); $cliente = get_post_meta(get_the_id(), 'cliente', TRUE); $descripcion = get_post_meta(get_the_id(), 'descripcion', TRUE); ?> <div class="portfolioItem"> <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"> <?php the_post_thumbnail('portfolioitem'); ?> <div class="portfolioItemDetalle"> <h2><?php the_title(); ?></h2> <?php if ($cliente) { echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; } if ($descripcion) { echo '<br /><div class="detalleTitul o">Descripcion</div> '.$descripcion.'</p>'; } ?> </div> </a> </div><!-- end of portfolioItem --> <?php endwhile; endif; ?> <div class="navigation"><?php wp_pagenavi(); ?></div> </div> <?php get_footer(); ?> Lo que hicimos en nuestro template es buscar el contenido de los custom fields cliente y descripcion y guardarlo en variables. Luego, dentro del bucle, nos fijamos si $cliente tiene algn contenido, de tenerlo entonces imprime lo que est luego del echo. Mismo caso para $descripcion. Como vern aadimos un tamao de thumbnail mas, as que lo tenemos que aadir a nuestro functions.php, en la seccin en donde estn los dems tamaos. add_image_size( 'portfolioitem', 230,230, true ); Y ya que estamos podemos aadir un snippet a nuestro functions.php que nos va a facilitar la carga de productos tambin. Este trozo de cdigo ya lo hemos visto en otras oportunidades en Summarg y resulta muy prctico. Bsicamente lo que hace es tomar la primer imagen que encuentre en la entrada y la convierte en destacada, salvo que el usuario haya elegido especficamente una. function autoset_featured() { global $post; $already_has_thumb = has_post_thumbnail($post->ID); if (!$already_has_thumb) { $attached_image = get_children( "post_parent=$post->ID&post_

108

type=attachment&post_mime_type=image&numberposts=1" ); if ($attached_image) { foreach ($attached_image as $attachment_id => $attachment) { set_post_thumbnail($post->ID, $attachment_id); } } } } //end function add_action('the_post', 'autoset_featured'); add_action('save_post', 'autoset_featured'); add_action('draft_to_publish', 'autoset_featured'); add_action('new_to_publish', 'autoset_featured'); add_action('pending_to_publish', 'autoset_featured'); add_action('future_to_publish', 'autoset_featured'); Buscaremos que nuestra plantilla tenga el siguiente formato: 109

Llegado este punto, y si ya tienen varios elementos cargados, necesitan regenerar las miniaturas para que muestre el nuevo formato. Pueden usar el plugin Regenerate Thumbnails que les va a ahorrar mucho tiempo y esfuerzo. Vamos con el CSS. /* plantilla taxonomia */ .portfolioItem { width: 230px; height:230px; float:left; position:relative; margin:0; padding:0; } .portfolioItem a { color:white; text-decoration:none; } .portfolioItem a img { border:none;

margin:0; } Necesitamos que .portfolioItem tenga position:relative ya que el contenedor que le sigue tendr que superponerse a nuestra imagen para lograr el efecto deseado, para lo cual usar position:absolute y le indicaremos que se posicione en top:0 y left:0. .portfolioItemDetalle { display:none; position:absolute; top:0; left:0; background-image:url(images/darky.png); background-repeat:repeat; padding: 10px; width: 210px; height:210px; color:white; margin:0; } .portfolioItemDetalle h2 { text-align:center; margin-top:20px; color:white; } Al contenedor con el ttulo y los detalles del trabajo le damos un display:none para ocultarlo, ya que queremos que se muestre nicamente cuando el usuario pase el mouse por arriba del elemento y luego se oculte. Con la siguiente lnea completamos el truco: .portfolioItem:hover .portfolioItemDetalle { display:block; } Listo! El truco funciona. Aunque Qu tal si ponemos un poquito de jQuery para animar esas ventanitas un poco? De ese modo podemos suavizar el efecto al pasar el mouse por arriba. Comentemos o eliminemos el ltimo trozo de CSS y coloquemos el siguiente cdigo en la plantilla de taxonoma luego del endif; <script type="text/javascript"> $(function() { $(".portfolioItem").hover(function() { $(this).children(".portfolioItemDetalle").show("fast"); },function(){ $(this).children(".portfolioItemDetalle").hide("fast"); }); }); </script> Con esto ya tenemos un bonito modo de mostrar nuestros items y dejamos las bases bien plantadas para que los lectores puedan tomar su propio rumbo a la hora de usar Custom Post Types. Pueden ver el producto terminado en el demo online.

110

Pgina personalizada para el portfolio con jQuery Isotope

Todava podemos hacer algo mas, un poco mas complicado y personalizado pero que va a quedar muy bien para lucir nuestro porfolio. Fuera de programa les vamos a regalar una integracin entre el plugin jQuery Isotope y nuestro portfolio. Creamos una pgina personalizada de nombre page-portfolio.php y colocamos en su interior exactamente lo que ya tenemos para taxonoma con pequeas diferencias: Agregamos el encabezado con el template name. Modificamos los argumentos de la query para que muestre cantidad ilimitada de elementos dentro del post_type que nos interesa. Eliminamos la lnea de paginacin ya que no vamos a usar ninguna. <?php /* template name: Portfolio + Isotope */ get_header(); ?> <div class="wrapperPortfolio"> <?php $args= array( 'posts_per_page' => 9999, 'post_type' => 'Portfolio' ); query_posts($args); if ( have_posts() ) : while ( have_posts() ) : the_post(); $cliente = get_post_meta(get_the_id(), 'cliente', TRUE); $descripcion = get_post_meta(get_the_id(), 'descripcion', TRUE); ?> <div class="portfolioItem"> <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"> <?php the_post_thumbnail('portfolioitem'); ?> <div class="portfolioItemDetalle"> <h2><?php the_title(); ?></h2> <?php if ($cliente) { echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; } if ($descripcion) { echo '<br /><div class="detalleTitulo">Decripcion</ div> '.$descripcion.'</p>'; } ?> </div> </a> </div><!-- end of portfolioItem --> <?php endwhile; endif; ?> <script type="text/javascript"> $(function() { $(".portfolioItem a").hover(function() { $(this).children(".portfolioItemDetalle").show("fast"); },function(){ $(this).children(".portfolioItemDetalle").hide("fast"); }); }); </script> </div> <?php get_footer(); ?> Creamos una pgina y le asignamos la plantilla que estamos construyendo. Descargamos desde

111

Isotope el plugin y lo anexamos a nuestro header. <script type="text/javascript" language="javascript" src="<?php bloginfo('template_directory'); ?>/scripts/jquery.isotope.min.js"></ script> Ahora bien, el plugin nos pide que respetemos una estructura de marcado determinada el men y para los elementos. Pueden ver aqu la documentacin (especficamente en lo que respecta a sorting) y les transcribimos el cdigo del demo de Isotope para que se den una buena idea. <ul id="sort-by"> <li><a href="#name">name</a></li> <li><a href="#symbol">symbol</a></li> <li><a href="#number">number</a></li> <li><a href="#weight">weight</a></li> <li><a href="#category">category</a></li> </ul> <div id="container"> <div class="element transition metal" data-category="transition"> <p class="number">79</p> <h3 class="symbol">Au</h3> <h2 class="name">Gold</h2> <p class="weight">196.966569</p> </div> <div class="element metalloid" data-category="metalloid"> <p class="number">51</p> <h3 class="symbol">Sb</h3> <h2 class="name">Antimony</h2> <p class="weight">121.76</p> </div> </div> Entonces nosotros intentaremos adaptar esa estructura a nuestro trabajo para que funcione el plugin. Debajo de la llamada de get_header() insertamos el men desde el que llamaremos a cada una de las taxonomas para que se muestren. <div id="options"> <ul id="filters" data-option-key="filter"> <li><a href="#filter" data-option-value="*">Todos</a></li> <li><a href="#filter" data-option-value=".Logos">Logos</a></li> <li><a href="#filter" data-option-value=".Packaging">Packaging</a></li> <li><a href="#filter" data-option-value=".Websites">Sitios Web</a></li> <li><a href="#filter" data-option-value=".Tarjetas">Tarjetas</a></li> </ul> </div> Inmediatamente despus de que se inicia el bucle necesitamos obtener el nombre de la taxonoma para colocarla en la clase de cada elemento, de ese modo el plugin puede traer a cada elemento cuando el usuario clickee en el men. $terms = get_the_terms( $post->ID , 'portfoliotaxonomies' ); foreach ( $terms as $term ) { $isotopeClass = $term->name; }

112

El nombre de la taxonoma se almacena en $isotopeClass, y ahora debemos imprimirla en nuestros elementos. <div class="portfolioItem isotopeElement <?php echo $isotopeClass; ?>"> <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"> <?php the_post_thumbnail('portfolioitem'); ?> <div class="portfolioItemDetalle"> <h2><?php the_title(); ?></h2> <?php if ($cliente) { echo '<p><div class="detalleTitulo">Cliente</div> '.$cliente; } if ($descripcion) { echo '<br /><div class="detalleTitulo">Descripci on</div> '.$descripcion.'</p>'; } ?> </div> </a> </div><!-- end of portfolioItem --> Con esto ya tenemos el marcado necesario y podemos proceder a aadir el cdigo javascript para que se ejecute el plugin. El siguiente cdigo debe anexarse al que ya habamos colocado para animar la aparicin de los detalles del item. <script type="text/javascript"> $(function(){ var $container = $('#isotopeArea'); $container.isotope({ itemSelector : '.isotopeElement', animationEngine : 'best-available' }); var $optionSets = $('#options .option-set'), $optionLinks = $optionSets.find('a'); $optionLinks.click(function(){ var $this = $(this); // don't proceed if already selected if ( $this.hasClass('selected') ) { return false; } var $optionSet = $this.parents('.option-set'); $optionSet.find('.selected').removeClass('selected'); $this.addClass('selected'); // make option object dynamically, i.e. { filter: '.my-filter-class' } var options = {}, key = $optionSet.attr('data-option-key'), value = $this.attr('data-option-value'); // parse 'false' as false boolean value = value === 'false' ? false : value; options[ key ] = value; if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) { // changes in layout modes need extra logic changeLayoutMode( $this, options ) } else { // otherwise, apply new options $container.isotope( options ); 113

} return false; }); }); </script> Con el parmetro animationEngine : best-available estamos indicando al plugin que utilice animaciones CSS3 cuando el navegador lo permita, y animaciones javascript en caso contrario. As que en nuestro CSS lo que tenemos que incluir son dichas transiciones. /** Isotope **/ .isotope, .isotope .isotope-item { /* change duration value to whatever you like */ -webkit-transition-duration: 0.8s; -moz-transition-duration: 0.8s; -ms-transition-duration: 0.8s; -o-transition-duration: 0.8s; transition-duration: 0.8s; } .isotope { -webkit-transition-property: height, width; -moz-transition-property: height, width; -ms-transition-property: height, width; -o-transition-property: height, width; transition-property: height, width; } .isotope .isotope-item { -webkit-transition-property: -webkit-transform, opacity; -moz-transition-property: -moz-transform, opacity; -ms-transition-property: -ms-transform, opacity; -o-transition-property: -o-transform, opacity; transition-property: transform, opacity; } /**** disabling Isotope CSS3 transitions ****/ .isotope.no-transition, .isotope.no-transition .isotope-item, .isotope .isotope-item.no-transition { -webkit-transition-duration: 0s; -moz-transition-duration: 0s; -ms-transition-duration: 0s; -o-transition-duration: 0s; transition-duration: 0s; } Y para concluir damos estilo al men que acabamos de agregar, que dicho sea de paso ser igual al #menu-top que construimos al principio del taller. /** Menu isotope **/ ul#filters { margin:20px 20px 0 0; float:right; list-style-type:none;

114

height:30px; width: 920px; } ul#filters li a{ list-style-type:none; text-decoration:none; float:right; color: #7ec5ff; font-weight:bold; padding: 7px 10px; font-size:12px; } ul#filters li a:hover { text-decoration:none; background-color: #7ec5ff; color:#fff; font-weight:bold; padding: 7px 10px; } Nota: para que este cdigo les funcione tal cual est aqu, deben crear exactamente las mismas taxonomas en Portfolio que nosotros publicamos. Sino simplemente efecten las modificaciones en donde corresponda en el men. Demo online Descargar clase themeTaller 17

115

Clase 18: Custom Post Types: Formulario de bsqueda.


El ltimo detalle que nos falta definir para los custom post types est relacionado con la creacin de un formulario de bsqueda en donde podamos listar elementos en base a diferentes parmetros. En nuestro Portfolio hicimos uso de dos custom fields y de taxonomas para clasificar nuestras entradas, y podra interesarnos listar entradas en base a dichos valores.

116

Vamos a crear una pgina personalizada para esta bsqueda y llamaremos al archivo pagesearch.php. <?php /* template name: search */ get_header(); ?> <div id="wrapper-dos"> <form name="searchcpt" class="searchcpt" action="<?php bloginfo('wpurl'); ?>/" method="get"> <p><strong>Buscador Portfolio</strong></p> <input name="" type="button" onclick="submit();" value="Buscar" class="btn" /> </form> </div><!-- end of wrapper--> <?php get_sidebar(); get_sidebar('dos'); get_footer(); ?> Ya colocamos las etiquetas de formulario y elegimos usar el layout que contiene dos barras laterales que construimos clases atrs. Lo primero que necesitamos hacer es establecer una diferencia entre este tipo de bsqueda y otros. Podramos tener varios CPT o mezclar este formulario con la bsqueda general del sitio, as que sera bueno definir que la bsqueda la realizaremos en el Portfolio, as que le vamos a pasar el parmetro con un input hidden (oculto). <input type="text" value="portfolio" hidden name="s" id="s" /> El primer custom field que utilizamos fue el que defina el layout as que generamos los radio buttons para que el usuario pueda elegir. <div class="seccionForm"> <div class="radiobuscar"> <input type="radio" name="layout" value="layout1"><div>Layout1</div> </div> <div class="radiobuscar"> <input type="radio" name="layout" value="layout2" checked><div>Layout2</

div> </div> </div> Ahora sera bueno colocar un select que permita seleccionar fcilmente una taxonoma, para lo que generaremos la funcin colocando el siguiente cdigo al final de nuestro functions.php function taxonomy_dropdown($taxonomy) { ?> <select name="cat" id="cat" class="postform"> <option value="">Elija secci&oacute;n</option> <?php $terms = get_terms($taxonomy); foreach ($terms as $term) { printf( '<option class="level-0" value="%s">%s</option>', $term->slug, $term->name ); } echo '</select>'; ?> <?php } ?> Dicha funcin recorre y lista los trminos dentro de la taxonoma que le indiquemos. En nuestra page-search.php colocamos la llamada a la funcin de la siguiente manera: <div class="selectArea"> <?php taxonomy_dropdown( 'portfoliotaxonomies' ); ?> </div> Finalmente nos sera de utilidad listar los socios de cada proyecto, pues cabe esperar que sea un dato que en mas de una oportunidad se repita. Para ello debemos realizar una consulta a la DB mediante $wpdb <div class="selectArea"> <select name="socio"> <option value="">Cualquiera</option> <?php $metakey = 'socios'; $socios = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = %s ORDER BY meta_value ASC", $metakey) ); if ($socios) { foreach ($socios as $socio) { echo "<option value=\"" . $socio . "\">" . $socio . "</option>"; } } ?> </select> </div> El CSS para esta seccin es el siguiente: .radiobuscar { width: 100px; float:left; margin: 0 0 5px 0; }

117

.radiobuscar div{ float:left; } .seccionForm { width: 380px; margin: 0 0 5px 0; float:left; } .selectArea { float:left; margin: 0 0 10px 0; } .searchcpt input[type=button] { float:left; border: 1px solid #7ec5ff; background-color: #7ec5ff; color: white; height:22px; font-weight:bold; font-size:11px; margin: 0 0 0 5px; padding: 5px 10px; overflow:hidden; } Hasta aqu pudimos construir el formulario, pero ahora debemos resolver la bsqueda. De paso podemos aprovechar a partir el formulario de bsquedas en dos archivos. Vamos a nuestro search.php y colocamos las siguientes lneas en la parte superior. Recuerden que deben cerrar la llave que se abre luego del else. $search_refer = $_GET["s"]; if ($search_refer == 'portfolio') { load_template(TEMPLATEPATH . '/ search-custom.php'); } else { En esta seccin utilizamos el primer input que colocamos en el formulario, que utilizamos nicamente para indicar que la variable s tiene por valor portfolio, y para tal caso escapa del template search.php y carga el template search-custom.php. Generamos el archivo search-custom.php y comenzamos a procesar los datos. Como primera medida usamos get_header() para cargar el encabezado y usamos GET para obtener las variables que pasamos por URL desde el formulario. <?php get_header(); $layout = $_GET["layout"]; $cat = $_GET["cat"]; $socio = $_GET["socio"]; Armamos la consulta con query_posts y pasamos todos los argumentos. En primer lugar indicamos el post_type, luego los trminos de portfoliotaxonomies. Para los valores de los custom fields utilizamos meta_query, y como usamos dos diferentes necesitamos introducir el parmetro relation para definir si se deben cumplir ambas condiciones o una u otra. Antes de los argumentos colocamos dos condicionales para cubrir las diferentes situaciones. Si $socio y $layout contienen valores, es decir que el usuario seleccion algo en ambos campos,

118

entonces la relacin que establecemos es AND y significa que se listarn las entradas que contengan los dos valores que pasamos (ej. que pertenezca a Socio X y que su Layout sea Layout1). Si $socio no contiene nada dentro y $layout si, entonces la relacin ser OR, lo que permite listar las entradas que cumplan una u otra condicin. if ($socio && $layout) { $relation = 'AND';} if (!$socio && $layout) { $relation = 'OR';} $args = array( 'post_type' => 'portfolio', 'portfoliotaxonomies' => $cat, 'meta_query' => array( 'relation' => $relation, array( 'key' => 'layout', 'value' => $layout, 'compare' => '=' ), array( 'key' => 'socios', 'value' => $socio, 'compare' => '=' ) ) ); query_posts( $args ); Llegado este punto ya podemos listar el resto de la plantilla con el bucle y los resultados. Para poder comprobar mejor el funcionamiento del formulario vamos a imprimir al pi de cada elemento el valor socio, layout y la taxonoma.

119

<div id="wrapper"> <h1>Resultados en el Portfolio</h1> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); $sociokey = get_post_meta(get_the_id(), 'socios', TRUE); $layoutkey = get_post_meta(get_the_id(), 'layout', TRUE);

$terms = get_the_terms( $post->ID , 'portfoliotaxonomies' ); foreach ( $terms as $term ) { $taxonomy = $term->name; } ?> <div class="dos-tercios listado"> <h2><a href="<?php the_permalink() ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2> <?php the_post_thumbnail('thumb'); the_excerpt(); ?> <?php echo $sociokey.' | '.$layoutkey.' | '.$taxonomy; ?> </div><!-- end of dos-tercios --> <?php endwhile; else: ?> <h2>No encontrado</h2> <p>Lo sentimos, intente utilizar nuestro formulario de b&uacute;squedas.</p> <?php endif; ?> <div class="navigation"><?php posts_nav_link('','<p align="right">Siguientes</p>','<p align="left">Anteriores</p>'); ?></ div> </div><!-- end of wrapper--> <?php get_sidebar(); get_footer(); ?> La intencin de este trabajo es darles una idea de cmo se pueden explotar los Custom Post Types. Este formulario puede ampliarse introduciendo la posibilidad de ingresar trminos o ms custom fields. Tambin llegado este punto podramos elegir cargar los socios como etiquetas y no como custom fields, ya que tambin pueden introducirse en la query y son mas fciles de gestionar. Ver el formulario online Descargar clase: themeTaller 18

120

Clase 19: Plugins y snippets recomendados


Compartimos con ustedes todos lospluginsysnippetsque consideramos que todo desarrollador debe tener para sacar el mximo provecho de la plataforma. Estos son los bsicos para la construccin de cualquier sitio WordPressaunque obviamente no son todos indispensables, sino que ayudan con diversas tareas.

Plugins

Askimet: Incluido enWordPress, su misin es combatir elspamen todo el mundo, totalmente gratuito. Google XML Sitemap: Generador automtico desitemaps. All in One WP Security: Medidas bsicas de seguridad para tu WP. Contact Form 7: El mejorpluginpara formularios, permite el envo de archivos y mucho mas. Efficient Related Posts: Entradas relacionadas, optimizado en vistas de cuidar el consumo de recursos. Regenerate Thumbnails:Pluginobligatorio para los desarrolladores dethemes, regenera las miniaturas en base a los tamaos que encuentra en el functions.php. Resize at upload plus: Permite establecer el tamao mximo de las imgenes (en ancho y alto), y cuando el mismo es superior redimensiona la imagen. WP-Pagenavi: Inserta paginacin con nmeros. WP SyntaxHighlighter: Permite insertar cdigo en las entradas y mostrarlo con colores segn el lenguaje. WP to Twitter: Enva aTwittercada artculo al ser publicado. Lightbox Gallery: Aade el efectolightboxa tus galeras nativas deWordPress. Simple Lightbox: Efectolightboxa tus imgenes, permite configurar animaciones e incluso un modoslideshow. WP Lightbox 2: Inserta el efectolightboxa imgenes individuales o a galeras. AWPCP:Another WordPress Classifieds Plugin, completsimopluginpara insertar clasificados en nuestro sitio. Dispone de variosaddons premium. Cart66 Lite:Plugindee-commerce, permite vender productos digitales, genera programas de afiliado, ultra liviano. E-Shop: Potenteplugindee-commercecon varias opciones de listado de producto, cargos por flete, varias pasarelas de pago. Jigoshop: Este es unpluginmuy extendido, que cuenta con variosaddons premium(ver categora Jigoshop en Codecanyon), cuenta con la posibilidad deseteardiferentes parmetros por producto (ej. talles de ropa, colores, etc). Muy completo. Woocommerce: Uno de lospluginsmas poderosos, ya que cuenta con una amplia variedad deaddonstanto en elsitio de sus desarrolladorescomo enCodecanyon. WP-e-commerce: Este es uno de lospluginsmas antiguos que todava sobrevive y se adapta muy bien. Tiene una alta compatibilidad con casi cualquiertheme y adems cuenta con sus pro121

piosaddons premium.

Simple Advert: Completo gestor debannersque se integra conWordPress pero tambin funciona en cualquier plataforma. Funciones de publicacin por tiempo,clicks o impresiones. Sistema de estadsticas. Soporta enlaces, imgenes oflash. W3 Total Cache: Uno de lospluginsde cache mas completos, acelera la carga de pgina y economiza recursos del servidor. WP Mobile Edition: Detecta automticamente a los usuarios que ingresan desde un dispositivo mvil y carga unthemeoptimizado para dicha resolucin. Any Mobile Theme Switcher: Igual al anterior pero dispone de mayor control permitiendo cargar unthemepor cada tipo de dispositivo mvil encontrado. WPTouch Mobile Plugin: Elpluginpara visualizar desde dispositivos mviles mas popular del mercado. WordPress Mobile Pack:El mas completoplugin para desarrolladores, incluye varias adaptaciones para determinados dispositivos, untheme default, unthemepara el escritorio deWordPressy mas. 122

Snippets
Aadir custom post types a los feeds. function myfeed_request($qv) { if (isset($qv[feed])) $qv[post_type] = get_post_types(); return $qv; } Cambiar la longitud de the_excerpt function my_excerpt($length) { return 150; } add_filter(excerpt_length, my_excerpt); Cambiar el texto de leer mas del excerpt <?php function new_excerpt_more($more) { return [much more to go]; } add_filter(excerpt_more, new_excerpt_more); ?> Colocar imagen destacada automticamente function autoset_featured() { global $post; $already_has_thumb = has_post_thumbnail($post->ID); if (!$already_has_thumb) { $attached_image = get_children( post_parent=$post-

>ID&post_type=attachment&post_mime_type=image&numberposts=1 ); if ($attached_image) { foreach ($attached_image as $attachment_ id => $attachment) { set_post_thumbnail($post->ID, $attachment_id); } } } } //end function add_action(the_post, autoset_featured); add_action(save_post, autoset_featured); add_action(draft_to_publish, autoset_featured); add_action(new_to_publish, autoset_featured); add_action(pending_to_publish, autoset_featured); add_action(future_to_publish, autoset_featured); Funcin para colocar una cantidad personalizada de texto /* Original Plugin URI: http://labitacora.net/comunBlog/limit-post.phps Usage: the_content_limit($max_charaters, $more_link) */ function the_content_limit($max_char, $more_link_text = (more...), $stripteaser = 0, $more_file = ) { $content = get_the_content($more_link_text, $stripteaser, $more_ file); $content = apply_filters(the_content, $content); $content = str_replace(]]>, ]]&gt;, $content); $content = strip_tags($content); if (strlen($_GET[p]) > 0) { echo <p>; echo $content; echo [...]</p>; } else if ((strlen($content)>$max_char) && ($espacio = strpos($content, , $max_char ))) { $content = substr($content, 0, $espacio); $content = $content; echo <p>; echo $content; echo [...]</p>; } else { echo <p>; echo $content; echo [...]</p>; } } Luego dentro del bucle se coloca: 123

<?php the_content_limit(150); ?> Aadir texto al final de nuestras entradas en los feeds function feedFilter($query) { if ($query->is_feed) { add_filter(the_content,feedContentFilter); } return $query; } add_filter(pre_get_posts,feedFilter); function feedContentFilter($content) { $content .= <p>Texto extra para los feeds... </p>; } return $content; 124

Aadir iconos segn el myme type del adjunto function get_attachment_icons($echo = false){ $sAttachmentString = <div class=documentIconsWrapper> \n; if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/pdf, //MIME Type condition ))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/pdf.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Word Documents if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/msword, //MIME Type condition

))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/word.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Powerpoint Documents if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/vnd.ms-powerpoint, //MIME Type condition ))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/PowerPoint.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Excel Documents if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/vnd.ms-excel, //MIME Type condition ))){

125

foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/XLS8.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Zipped Files if ( $files = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => application/zip, //MIME Type condition ))){ foreach( $files as $file ){ //setup array for more than one file attachment $file_link = wp_get_attachment_url($file->ID); //get the url for linkage $file_name_array=explode(/,$file_link); $file_name=array_reverse($file_name_array); //creates an array out of the url and grabs the filename $sAttachmentString .= <div class=documentIcons>; $sAttachmentString .= <a href=$file_link>; $sAttachmentString .= <img src=.get_bloginfo(template_directory)./images/mime/zip.png/>; $sAttachmentString .= </a>; $sAttachmentString .= <br>; $sAttachmentString .= <a href=$file_link>$file_name[0]</a>; $sAttachmentString .= </div>; } } //Audio Files $mp3s = get_children(array( //do only if there are attachments of these qualifications post_parent => get_the_ID(), post_type => attachment, numberposts => -1, post_mime_type => audio, //MIME Type condition ) ); if (!empty($mp3s)) :

126

$sAttachmentString .= <ul class=audiofiles>; foreach($mp3s as $mp3) : $sAttachmentString .= <li>; if(!empty($mp3->post_title)) : //checking to make sure the post title isnt empty $sAttachmentString .= <h4 class=title>.$mp3->post_ title.</h4>; endif; if(!empty($mp3->post_content)) : //checking to make sure something exists in post_content (description) $sAttachmentString .= <p class=description>.$mp3>post_content.</p>; endif; $sAttachmentString .= <object width=470 height=24 id=single.$mp3->ID. name=single.$mp3->ID.>; $sAttachmentString .= <param name=movie value=player.swf>; $sAttachmentString .= <param name=allowfullscreen value=true>; $sAttachmentString .= <param name=allowscriptaccess value=always>; $sAttachmentString .= <param name=wmode value=transparent>; $sAttachmentString .= <param name=flashvars value=file=.$mp3->guid.>; $sAttachmentString .= <embed ; $sAttachmentString .= id=single.$mp3->ID. ; $sAttachmentString .= name=single.$mp3->ID. ; $sAttachmentString .= src=.get_ bloginfo(template_directory)./jw/player.swf ; $sAttachmentString .= width=470 ; $sAttachmentString .= height=24 ; $sAttachmentString .= bgcolor=#ffffff ; $sAttachmentString .= allowscriptaccess=always ; $sAttachmentString .= allowfullscreen=true ; $sAttachmentString .= flashvars=file=.$mp3>guid. ; $sAttachmentString .= />; $sAttachmentString .= </object>; $sAttachmentString .= <a href=.$mp3>guid.>Download</a>; $sAttachmentString .= </li>; endforeach; $sAttachmentString .= </ul>; endif; $sAttachmentString .= </div>; if($echo){ echo $sAttachmentString;

127

} add_shortcode(attachment icons, get_attachment_icons); Acortar el ttulo a determinada cantidad de caracteres: function the_title2($before = , $after = , $echo = true, $length = false) { $title = get_the_title(); if ( $length && is_numeric($length) ) { $title = mb_substr( $title, 0, $length, UTF-8 ); } if ( strlen($title)> 0 ) { if ( strlen($title) == $length ) $title = apply_filters(the_title2, $before . $title . $after, $before, $after); if ( $echo ) echo $title; else return $title; } } Luego en el theme colocar la funcin con la cantidad de caracteres a imprimir: <?php the_title2(15); ?>

} return $sAttachmentString;

128

Conclusin
WordPress se populariz como plataforma para blogs, pero fue convirtindose en un potente CMS a la altura de Joomla o Drupal. El diseo de plantillas para WordPress es realmente simple, como pudimos ver, y con los conocimientos previos necesarios nos permite en poco tiempo conquistar la construccin de themes y explotar al mximo las capacidades de la plataforma. No se necesitan grandes conocimientos de php, solo una base sobre la lgica de programacin y algunas funciones sueltas aqu y all. Lo que si resulta importante es tener una buena base de HTML y CSS, y aade un plus especialmente interesante el tener buenos conocimientos de jQuery. La inclusin de los Custom Post Types, adems de los mens, las miniaturas personalizables y otros detalles, marcaron en WordPress un antes y un despus en lo que respecta a disear sitios con organizaciones complejas de contenidos pero manteniendo la simplicidad de uso para el editor y usuario comunes. 129 Una de las cosas que mas nos atrap de WordPress es que al lado de sus competidores resulta muy liviano para el servidor y dispone de actualizaciones constantes parcheando las vulnerabilidades y bugs que surgen. Cada da emergen mas herramientas para administrar mltiples instalaciones de WordPress, backupeos automticos, plugins con medidas de seguridad extra y antivirus que detectan e informan de cualquier cdigo extrao que logre filtrarse. Si bien no es imposible de vulnerar un sitio hecho con WordPress, sigue siendo bastante confiable tomando las medidas del caso. La comunidad desarrolladora es cada da mas grande, y esto impacta directamente en el nmero de plugins y themes disponibles. En resumen, no por nada hoy es la plataforma mas popular del mercado y miles de miles de personas basan su trabajo en WordPress. Esperamos que ustedes disfruten de este taller tanto como nosotros y que puedan sacarle provecho en sus trabajos o como hobbie.