Use get_the_terms() instead of wp_get_object_terms()

I was recently debugging the front page of a WordPress site and found a lot of queries to the terms and term relationships database tables.

Digging a little deeper, I found that the culprit were a set of functions that were calling wp_get_object_terms() to get the terms from a set of looped posts… and then I thought… “wait a minute, doesn’t WordPress should be using the object cache for this?”

Well, it turns out that wp_get_object_terms() always queries the database.

If you’re looping over WP_Query results, you should prefer get_the_terms() instead. It’s pretty much the same for most use cases, but it uses the object cache, which by default gets populated with the terms for the posts matching your query — unless you specifically set update_post_term_cache as false when instantiating WP_Query.

The are several differences, though: wp_get_object_terms() can take arrays as the first and second argument, while get_the_terms() can only take the post ID (or object) as first argument (so you can’t get the terms for a bunch of posts on one function call) and a string for taxonomy (so you can’t get the terms for several taxonomies); and you can use a third argument on the former, which the latter doesn’t have.

You could still emulate some of this, and still benefit from using the object cache; for instance, let’s see how you would get the names of the my_custom_tax terms for the current post, ordered by use on a descending way.

// using wp_get_object_terms()
$popular_terms = wp_get_object_terms( $post->ID, 'my_custom_tax', array( 
    'orderby' => 'count',
    'order'   => 'DESC',
    'fields'  => 'names'
) );

// using get_the_terms()
$popular_terms = get_the_terms( $post->ID, 'my_custom_tax' );
// $popular_terms will be ordered alphabetically, so let's order by count
$popular_terms = usort( $popular_terms, function( $a, $b ){
    if ( $a->count < $b->count ) {
        return 1;
    }
    if ( $a->count > $b->count ) {
        return -1;
    }
    return 0;
} );  
// we only need slugs, so...
$popular_terms = wp_list_pluck( $popular_terms, 'name' );

Even if it’s somewhat troublesome, it’s probably worth the effort if you’re trying to maximize for performance.

TPP has provision banning requirements to transfer of or access to source code of software

El texto del TPP contiene disposiciones que prohíben la transferencia o acceso al código fuente del software, lo que podría constituir una seria amenaza a la validez de licencias de código abierto con copyleft, en particular la GPL.

Cómo agregar un nuevo panel a WordPress Debug Bar

Una de las ventajas del plugin WordPress Debug Bar es que puedes agregar nuevos paneles según tus propias necesidades; por ejemplo, para mostrar datos de respuestas desde APIs externas o conexiones con web services u otras funcionalidades que hayas implementado de forma particualr.

// el plugin utiliza el filtro 'debug_bar_panels'
// que puedes usar para agregar nuevos paneles
add_filter( 'debug_bar_panels', 'my_custom_panel_init' );

/**
 * Inicializar tu panel personalizado
 * @param array $panels Instancias de Paneles
 * @return array
 */
function my_custom_panel_init( $panels ) {
    // Debes extender la clase Debug_Bar_Panel que forma
    // parte del plugin
    class Debug_Bar_Custom_Panel extends Debug_Bar_Panel{
        public function init(){
            // Como mínimo, debes definir el título de tu panel
            // personalizado. Se usará como título de la pestaña
            $this->title( 'Panel Personalizado' );
        }
        public function render(){
            // Construye e imprime el contenido de la pestaña
        }
    }
    // Agrega tu pestaña a la barra de depuración
    $panels[] = new Debug_Bar_Custom_Panel();
    return $panels;
}

Por supuesto, este es un ejemplo simplificado, pero es el punto de partida para tu implementación. Con un par de líneas más ya puedes tener tu propio panel:

Agregar un panel de depuración personalizado a WordPress Debug Bar

Para un ejemplo más completo, puedes revisar el código de alguno de los plugins que extienden la funcionalidad de la barra de depuración, como el repositorio de Debug-Bar-Shortcodes.

Usar DISQUS en sitios multilenguaje

Recientemente rediseñamos el sitio de nuestra aplicación para la gestión de hoteles, y uno de los cambios más importantes fue poder ofrecer una mejor experiencia a los visitantes según su idioma. También nos interesaba tener una mejor interacción en los comentarios del blog, y para ello decidimos utilizar la plataforma de Disqus, que entre otras cosas, permite suscripciones por correo electrónico a los comentarios, identificación con cuentas de terceros, moderación por e-mail, etc.

Uno de los problemas que encontramos fue que Disqus tiene una configuración global para la cuenta, por lo que la opción que configuras en su panel aplica a todas las conversaciones en el sitio. Sin embargo, escudriñando el código del plugin para WordPress pude hallar un filtro que permite indicar explícitamente el idioma en que se debe cargar la sección de comentarios:

add_filter('disqus_language_filter', function( $lang ){
	// la función pll_current_language es del plugin polylang; y devuelve el idioma de la entrada actual
	$current_language = function_exists('pll_current_language') ? pll_current_language('locale') : 'es_ES';
	// ojo que en Disqus, inglés es "en" pero español "es_ES" :-P
	return $current_language == 'en_US' ? 'en' : $current_language;
});

Y si no estás usando WordPress, puedes indicar el idioma en la configuración del embebible.

Cómo asegurar las cookies de acceso a tu sitio WordPress

Recientemente se ha dado a conocer una vulnerabilidad en el sistema de autenticación de usuarios para los sitios con WordPress, que básicamente consiste en lo siguiente:

  • La vulnerabilidad afecta tanto a sitios en WordPress.com como instalaciones propias.
  • Al acceder a la administración de tu sitio, WordPress crea una cookie que le permite validarte como un usuario que ha iniciado sesión.
  • Una gran cantidad de sitios con WordPress no funciona sobre HTTPS, por lo que la cookie se envía como texto plano.
  • Un atacante puede interceptar esa cookie, insertarla en su navegador, y luego hacerse pasar por el usuario que ha iniciado sesión. Esto es particularmente fácil en situaciones donde hay transmisiones “abiertas” de datos, por ejemplo en un café donde la conexión no tiene contraseña.
  • La cookie sigue siendo válida aun cuando el usuario cierre su sesión, por lo que podrías ingresar a tu administrador, cerrar la sesión, y el atacante aun tendría acceso.
  • El tiempo de expiración de la cookie es de 3 años en blogs de WordPress.com y 14 días en instalaciones propias.

Ahora pasemos a lo importante, ¿cómo evitarlo?

En primer lugar, la opción más sencilla pero seguramente inefectiva es la abstinencia: simplemente, evitar acceder a la administración de WordPress en redes no confiables. Pero como estamos hablando de seguridad, y en este sentido no se puede ser demasiado paranoico, desechemos esta opción.

Continue reading “Cómo asegurar las cookies de acceso a tu sitio WordPress”

Las secuelas de Heartbleed

Heartbleed es —en términos sencillos— el cagazo más grande que se ha descubierto en materia de seguridad informática en muchos años, y que en el contexto de las revelaciones que hemos conocido gracias a la denuncia de Edward Snowden no sólo ayuda a explicar algunas cosas sino también a ponernos a todos un poco más paranoicos.

Por ello es que los coletazos de su descubrimiento están lejos de terminar, y esto no se refiere únicamente a la multitud de sitios que aún estarán exponiendo a sus usuarios a esta vulnerabilidad, sino también a las deficiencias en procesos críticos que han quedado al descubierto por esta crisis mientras la polvareda aún no termina de asentarse.

En particular, existen dos iniciativas en las que vale la pena reparar porque representan dos caras muy distintas del mundo del software libre y el código abierto.

Continue reading “Las secuelas de Heartbleed”