Enjoyable WordPress theming with Timber (and ACF)

I was thinking of doing an in-depth tutorial on Timber. A few days since I started a draft, CSS-Tricks published “Timber and Twig Reignited My Love for WordPress“, which is a great read. However, I decided to push some of it live because this plugin deserves more love.


I’ve built a lot of WordPress sites. Recently, it has become more tedious work for me. Not for their complexity —most of corporate sites are fairly straightforward—, but because of the amount of work you have to do in Spaghetti code.

This situation changed when I found two amazing plugins: ACF (Advanced Custom Fields) and of course, Timber.

ACF lets you define additional custom fields on posts and pages (or even custom post types), without having to mess around with weird admin code and functions.php. Seriously, go check it out, buy the PRO version.

On the other hand, Timber “helps you create fully-customized WordPress themes faster with more sustainable code. With Timber, you write your HTML using the Twig Template Engine separate from your PHP files.”

Getting started

Install Timber through the WordPress admin or by downloading it from GitHub.

That’s it! At this point you’re ready to use Timber. You can start using it right now with your current theme files.
However, if you’re starting from zero I strongly recommend using Timber’s Starter Theme.

Once you’re there, you’ll find all your PHP files on the root, and on /template folder all twig files, with .twig extension. That way, every bit of logic stays separated from the presentation.

The documentation on Timber, ACF and Twig is detailed and clear. So go check them out and start building cleaner, more maintainable websites!

Loop list in batches using Twig (or plain PHP)

Recently I had to loop through a series of elements in a WordPress template (thanks Timber), which happened to be using Bootstrap.

If you ever used Bootstrap, you are familiar with the following markup:

The problem here is very common. You have to:

  • Loop every 3/4/n items.
  • Insert a separator or whatever every 3/4/n items.

You can achieve this with modulo (divisibleby) and checking if the loop index is last and other weird magic. However, Twig introduced the batch filter in version 1.12.3, where you can make this much less cumbersome.

So, adapting the current example and their docs, this is how we achieve a clean loop:

Much better, right?

I realized PHP has a built-in function that handles this. It’s called array_chunk which, of course, splits an array into chunks (or batches as I recalled, and the reason why I hadn’t been able to find it on the docs.)

Edit 19 Jul: Added plain PHP version.

Sync local and remote WordPress database

This is just a big heads-up to every WordPress developer out there, just to let them know that syncing a development/staging database doesn’t have to be a nightmare.

There’s this plugin called WP Sync DB which works like magic.

As a reader also suggests, WP Sync DB also has plugins that build upon the main funcionality. For example, wp-sync-media-files, to sync also, well, media files. But there are more.

  • GitHub Repo: https://github.com/wp-sync-db/wp-sync-db
  • Website: http://wp-sync-db.github.io/
  • WP Sync DB GH Page (repo and more plugins): https://github.com/wp-sync-db

Fest Contrapedal 2013

Ayer lanzamos junto a GRMN y todo el equipo de Contrapedal el sitio web del Fest, edición 2013.

Este será primer trabajo oficial bajo el nombre de MONTAG, proyecto que formamos junto a Germán.

Los invito a visitar el sitio, ver la programación y asistir a los espectáculos, el baratón, paneles e instalaciones:

Fest Contrapedal 2013

 

Enlaces

 

Vulnerabilidad en varios Themes de WordPress

Ha sido detectada una vulnerabilidad seria en el script Timthumb, un script para redimensionar imágenes desde el servidor escrito en PHP e incluído en muchos themes de WordPress.

Al parecer podría haber varias formas para evitar el riesgo, una de ellas es esta:

  1. Descargar la última versión del plugin: Timhumb 1.33.
  2. Buscar el archivo del plugin (con SSH podemos hacer ” find . -name ‘timthumb.php’ “).
  3. Ir a la línea 27, que debería comenzar con $allowedSites = array (... y cambiar la lista de sitios permitidos por $allowedSites = array();
  4. Guardar el archivo.

Hay otras alternativas que quizá puedan funcionar, pueden verlas en los comentarios del post donde se anunció la vulnerabilidad: Zero day vulnerability in many WordPress themes.

Indicador de entradas pendientes de revisión en WordPress

Como sabrán, para cada entrada WordPress trae por defecto tres estados: Publicado, Borrador y Pendiente de revisión. Este último es útil sobre todo para los casos en que una persona escribe una entrada y otra se encarga de revisarla, previo a su publicación. Puede ser el caso de un blog con varios autores o alguno que cuente con un editor.

En Ted el Mecánico usamos mucho esta funcionalidad, ya que hacemos una especie de revisión cruzada. Uno escribe una entrada, otro usuario entra, revisa los pendientes y publica.

Hasta ahí todo funciona bien. El problema es que la única manera de saber si hay entradas pendientes es entrando al listado de entradas. Los comentarios, que también tienen un estado similar (Pendiente de aprobación) cuentan con un indicador en el menú lateral:

Indicador de comentarios pendientes

La pregunta es: ¿Porqué las entradas pendientes de revisión no se comportan así por defecto? Fácilmente podríamos tener algo así:

Indicador de entradas pendientes de revisión

Sin embargo, mientras no se implemente este comportamiento, se puede recurrir a plugins. Existe un plugin que dice hacer exactamente eso. Se llama Pending Posts Indicator.

La única desventaja que tiene es que nos hardcodea el título “Posts” y por alguna extraña razón, quita el ícono del título. Para corregir esto, hay que actualizar el único archivo del plugin, en la línea 27:
$menu[5] = array( sprintf( __('Posts %s'), "<span class='update-plugins count-$pending_count'><span class='plugin-count'>" . number_format_i18n($pending_count) . "</span></span>" ), 'edit_posts', 'edit.php', '', 'wp-menu-open menu-top', 'menu-posts', 'div' );

Sustituírlo por:
foreach( $menu as $menu_key => $menu_data ) :
if( 'edit.php' != $menu_data[2] )
continue;
$menu[$menu_key][0] .= " <span class='update-plugins count-$pending_count'><span class='plugin-count'>" . number_format_i18n($pending_count) . '</span></span>';
endforeach;

(El crédito de parte de los cambios es de t31os.)

Ya me contacté con el autor del plugin original, para que incluya los cambios y así esté disponible desde el directorio de plugins de WordPress. Mientras tanto se puede descargar la versión 1.1 de aquí:

[download id=”4″]

Momentos luego de recibir el cambio anterior postearon otra respuesta en StackExchange, que contempla el caso de  Custom Post Types pendientes: Ver respuesta en StackExchange.

Actualizado 12/11/2010 20:00 – Subí un ticket al trac de WordPress (ticket 150406). En el peor de los casos, obtengo una respuesta de porqué no está implementado, en el mejor, se implementa el patch y todos felices :)

Actualizado 14/11/2010: El ticket fue actualizado y aparentemente fue agendado para “Future Release”!

Enlaces

Listar y paginar Custom Post Types en WordPress

Los tipos de datos customizados (Custom Post Types) en WordPress fueron uno de los agregados más importantes de la versión 3. Agregan a la plataforma un soporte nativo para cualquier tipo de dato, conviertiendose cada día más en un CMS completo (nos guste o no.)

En la entrada Custom Post Types en WordPress se puede ver como crear un custom post type de tipo libro. Tienen infinitas utilidades, pero en muchas ocasiones vamos a necesitar por lo menos una página con un listado y una página individual para mostrar un ítem de ese tipo. Para el primer caso, seguramente queramos un paginado.

Hoy en día la manera más sencilla de hacer esto es utilizar la clase SD_Register_Post_Type de Soma Design. Aunque quizá en un futuro este comportamiento esté integrado en la plataforma, hoy es difícil hacerlo sin plugins, sobre todo para el que no conoce mucho el código de WordPress.

La funcionalidad más interesante que provee es:

  1. URLs customizadas para el listado general de un post type, con paginación y feed.
    Ej.: http://sitio.com/libros/, http://sitio.com/libros/page/2/http://sitio.com/libros/feed/ )
  2. Plantillas customizadas para lista de ítems y páginas individuales. Si registramos “libro” como post type, podremos usar libro/single.php (individual) y libro/index.php (lista) para una mejor organización.

Modo de uso

Primero debemos incluír la clase SD_Register_Post_Type en nuestro código. Se puede incluír desde un archivo externo:
require_once('sd_register_post_type.class.php')
o copiar la clase entera a nuestro código (dentro de functions.php por ejemplo.)

Lo único que resta es registrar el nuevo tipo de dato utilizando la función auxiliar sd_register_post_type:

sd_register_post_type('libro', $args, 'libros')

Esta función es simplemente un wrapper de register_post_type, recibe los mismos parámetros(nombre, array de parámetros) más un tercer parámetro para el nombre plural del tipo. Si no se especifica el segundo y tercer parámetro se toman valores por defecto, en el caso del plural se agrega una s al nombre del tipo.

Gracias a eso, se puede reutilizar el código utilizado con register_post_type con esta nueva función:

sd_register_post_type( 'libro',
    array(
	'public' => true,
	'labels' => array(
		'name' => __( 'Libros' ),
		'singular_name' => __( 'Libro' ),
		'add_new' => __( 'Añadir Libro' ),
		'add_new_item' => __( 'Añadir Nuevo Libro' ),
		'edit' => __( 'Editar' ),
		'edit_item' => __( 'Editar Libro' ),
		'new_item' => __( 'Nueva Libro' ),
		'view' => __( 'Ver Libro' ),
		'view_item' => __( 'Ver Libro' ),
		'search_items' => __( 'Buscar Libro' ),
		'not_found' => __( 'Libro No Encontrado' ),
		'not_found_in_trash' => __( 'Libro no encontrado en Papelera' )
	),
	'description' => __( 'Libros y revistas' ),
	'menu_position' => 20,
	'menu_icon' => get_stylesheet_directory_uri() . '/images/libros.png',
	'query_var' => true,
	'supports' => array(
		'title',
		'editor',
		'comments',
		'trackbacks',
		'page-attributes',
		'thumbnail' ),
	'rewrite' => array( 'slug' => 'libros'), //->Ver Error 404
	'capability_type' => 'post'
    )
)

Error 404

Como en el caso de la entrada anterior, los cambios de las URLs no van a tener efecto hasta visitar Ajustes>Enlaces Permanentes (Permalinks) para refrescar las reglas de permalinks.

Luego de seguir esos pasos deberías poder administrar libros desde el panel de administración de WordPress y visualizar libros individuales (por default cargados en la plantilla single.php.)

Paginado

Para tener una plantilla con un listado de libros con paginado, creamos un archivo libro/index.php dentro de la carpeta del theme activo y agregamos el código siguiente para traer los posts de la base de datos:

$wp_query = new WP_Query(array('post_type' => 'libro',
                                 'paged' => $paged,
                                 'posts_per_page' => 30,
				 'orderby' => 'title',
				 'order' => 'ASC')
);

Eso seleccionaría 30 libros por página, ordenados por título en forma ascendiente. Por último faltaría agregar los links de paginación. La manera más sencilla es agregando next_posts_link('Página siguiente') y previous_posts_link('Página anterior').

Se puede ver un código similar funcionando en el blog Ted el Mecánico, en la sección de Salas. Se puede ver la página 2 del listado o la página individual de La Trastienda, por ejemplo.

Links

  • http://codex.wordpress.org/Custom_Post_Types
  • http://codex.wordpress.org/Custom_Fields
  • http://somadesign.ca/projects/smarter-custom-post-types/
$wp_query = new WP_Query(array(‘post_type’ => ‘ted_venue’,
‘paged’ => $paged,
‘posts_per_page’ => 30,
‘orderby’ => ‘title’,
‘order’ => ‘ASC’)
);

WordPress plugin: Undo Publish

Undo Publish es un un pequeño experimento de plugin, inspirado en la funcionalidad Undo Send de Gmail Labs, que ofrece la misma funcionalidad pero en el panel de WordPress. En pocas palabras permite cancelar la publicación de un post nuevo dentro de los 3 segundos posteriores a su publicación.

Configuración

El plugin no tiene opciones de configuración dentro del panel de administración de WordPress. Sin embargo, editando el archivo del plugin se puede configurar el tiempo de espera que permite antes de publicar el post. La variable a editar es define(TIME_LIMIT, 3000), en milisegundos.

Notas

  • El plugin se activa solamente para posts que sean nuevos. Es decir, no va a molestar cuando la acción sea Actualizar un post.
  • Se activa también para Custom Post Types (No se si es un bug o un feature, depende del Custom Post Type, creo yo.)

Instalación

  • Descomprimir en wp-plugins/
  • Activar.

Descarga

Pueden descargarlo del repositorio oficial de WordPress, incluyo el link aquí abajo.

Undo Publish – WordPress Plugin Directory

http://wordpress.org/extend/plugins/undo-publish/

http://wordpress.org/extend/plugins/undo-publish/

Custom Post Types en WordPress

Primero que nada, ¿Qué son Custom Post Types?

Los tipos  de datos que maneja WordPress nativamente son post, page, attachment, revision y nav menu. Los Custom Post Types son básicamente tipos de datos personalizados, algo así como los Content Types de Drupal. Son infelizmente llamados Post Types porque viven en la misma tabla que posts y pages (wp_posts), y son diferenciados por una columna post_type.

Definir nuevo custom post type

Para definir un tipo nuevo utilizamos la función create_post_type(). El siguiente código puede ser utilizado desde el archivo functions.php o aún mejor, desde un plugin.

add_action( 'init', 'create_post_type' );
function create_post_type() {
  register_post_type( 'libro',
	array(
		'public' => true,
		'labels' => array(
			'name' => __( 'Libros' ),
			'singular_name' => __( 'Libro' ),
			'add_new' => __( 'Añadir Libro' ),
			'add_new_item' => __( 'Añadir Nuevo Libro' ),
			'edit' => __( 'Editar' ),
			'edit_item' => __( 'Editar Libro' ),
			'new_item' => __( 'Nueva Libro' ),
			'view' => __( 'Ver Libro' ),
			'view_item' => __( 'Ver Libro' ),
			'search_items' => __( 'Buscar Libro' ),
			'not_found' => __( 'Libro No Encontrado' ),
			'not_found_in_trash' => __( 'Libro no encontrado en Papelera' )
		),
		'description' => __( 'Libros y revistas' ),
		'menu_position' => 20,
		'menu_icon' => get_stylesheet_directory_uri() . '/images/libros.png',
		'query_var' => true,
		'supports' => array(
			'title',
			'editor',
			'comments',
			'trackbacks',
			'page-attributes',
			'thumbnail' ),
		'rewrite' => array( 'slug' => 'biblioteca'), //->Ver Error 404
		'capability_type' => 'post'
	)
  );
}

La función create_post_type() recibe como primer parámetro el nombre del tipo de dato y en segundo lugar una lista de parámetros para configurarlo. Aquí se puede ver el detalle de esta función: Function reference: register_post_type.

Luego de añadir ese código deberíamos ver un menú lateral “Libros” que nos permite gestionar nuevos elementos de tipo libro, tal como manejamos posts o páginas. Con el parámetro rewrite especificamos que las urls serán del tipo http://sitio.com/biblioteca/nombre-libro.

Error 404

Al editar el nuevo tipo de dato es posible encontrarse con errores de página no encontrada, al hacer preview o al visitar un nuevo ítem publicado si utilizamos el parámetro rewrite para hacer uso de permalinks. Para corregir esto basta con visitar Settings/Permalinks o agregando flush_rewrite_rules() luego de llamar a register_post_type().

Definir campos para el nuevo tipo de datos

A través del array supports podemos definir los campos nativos que contiene nuestro tipo de datos, por ejemplo title, editor (contenido), comments, etc. Pero también podemos añadir nuevos campos. Supongamos que quiero agregar un nuevo campo Editorial al tipo Libro.

Para esto hay que agregar un meta_box (las cajitas con opciones dentro de post.php) en la administración para poder editar ese campo. Esto se hace mediante la función add_meta_box().

add_action("admin_init", "admin_init");

function admin_init(){
    add_meta_box("libro-meta", "Información Extra", "info", "libro", "side", "low");
}

function info(){
    global $post;
    $custom = get_post_custom($post->ID);
    $capacity = $custom["editorial"][0];
    ?>
        <label for="capacity">Editorial</label>
        <input name="capacity" id="capacity" value="<?php echo $capacity; ?>" />
    <?php
}

Por último, registramos una función para guardar los campos personalizados.

add_action('save_post', 'save_extra');
function save_extra(){
    global $post;
    update_post_meta($post->ID, 'editorial', $_POST['editorial']);
}

Listo. Ahora además de posts y pages podemos crear Libros. Cómo mostrarlos, eso es tema para otro post :)

Desgargar código fuente

[download id=”3″]

Probado en WordPress 3.0.

Fuentes

  • http://codex.wordpress.org/Custom_Post_Types
  • http://codex.wordpress.org/Function_Reference/register_post_type
  • http://thinkvitamin.com/dev/create-your-first-wordpress-custom-post-type/