Migrando el blog a WordPress

Hace algunos días el blog dejó de funcionar, probablemente por una actualización de los servidores de mi proveedor, 1&1, que invalidaba las reglas de Apache rewrite que escribí. Sí, son cosas que apestan de los servidores compartidos, pero lo he aprovechado para “matar moscas a cañonazos” y migrar todo el blog a WordPress.

El antiguo blog funcionaba con un software PHP escrito por mí siguiendo el patrón Multivista y usaba plantillas Smarty. Mis razones para migrar a WordPress:

  1. Compatibilidad con los servidores: el .htaccess de WordPress es más tolerante que el mío a los cambios caprichosos de 1&1.
  2. Tener un software más seguro, más probado y más potente.
  3. Los experimentos que haga con el blog (sobre todo de cosas relacionadas con web semántica) los escribiré como plug-ins de WordPress y así otras personas los podrán probar.
  4. El back-end de WordPress es infinitamente mejor que el mío.
  5. Utilizar la plantilla Twenty Eleven como base para el diseño, por su calidad de código HTML5 y CSS.
  6. Seguir aprendiendo WordPress.
  7. Rendimiento: WP-Cache y WP Super Cache me ahorrarán un trabajo que me daba pereza empezar.

Este ha sido, a grandes rasgos, el procedimiento que he seguido para la migración:

Uno: migrando los artículos

Esto no ha sido difícil, ya que he escrito un sencillo plug-in que se conecta a la BD antigua, recorre todos los artículos (con sus tags) y los introduce en WordPress con la función wp_insert_post().

Dos: migrar los comentarios

Cuando ya tenía todo listo me di cuenta de que había olvidado migrar los comentarios… así que los migré no programando un plug-in (como hice con los artículos) sino exportando los comentarios de la antigua base de datos a CSV, adaptando las columnas a la tabla wp_comments e importándolo a esta con phpMyAdmin.

Tres: adaptando el theme

Me he basado en Twenty Eleven, el theme por defecto de WordPress 3.2.1, que utiliza HTML5, soporta widgets, traducción y muchas otras cosas. La labor de theming, cuando ya tienes el diseño maquetado (el antiguo blog) es más laborioso que difícil, así que en un par de horas estuve despachado. También he aprovechado para hacer algunos cambios en el diseño, intentando que quede más limpio y simple, y cambiando los enlaces para compartir los posts en redes sociales.

Cuatro: organizando el contenido

Unos minutos de taxonomías, tipos de entradas, categorías, etc para tenerlo todo bien ordenadito.

Cinco: desplegando

Con el contenido migrado y organizado y el theme adaptado, ya puedo instalar en el servidor una nueva instancia de WordPress, subir el theme e importar el contenido con la herramienta Importar/Exportar de WordPress. El resto de tareas las hago directamente en el servidor de producción.

Seis: instalar plug-ins y retoques finales

Con el blog ya montado y funcionando sobre WordPress, completo la sección de contacto con Contact Form 7, enlazo el RSS con Feedburner, inserto el código de Google Analytics en el theme, añado el plug-in para resaltado de código fuente WP-Syntax y reviso que no hay enlaces rotos en los artículos con Broken Link Checker.

Siete: redirecciones 301 para no perder posicionamiento en buscadores

Con el blog en WordPress, las antiguas URL de los artículos se pierden, así que para evitar que los buscadores reindexen todo el contenido de nuevo y pierda el posicionamiento de mis artículos, he configurado redirecciones para cada uno de los artículos. La cabecera 301 “moved permanently” le indica a los buscadores que la página ha sido movida permanentemente a otra dirección, pero que sigue siendo la misma página.

Las redirecciones las he puesto en un script que es llamado desde la plantilla 404.php del theme, de forma que cuando se solicita una URL antigua se produce un error 404 controlado por WordPress, pero antes de que se lance la cabecerar 404 y página de error, mi script comprueba si esa URL es de las antiguas y redirige, con una cabecera 301, a la URL correcta.

ACTUALIZACIÓN 16/dic/2012: después de un año con WP-Syntax he cambiado a SyntaxHighlighter Evolved, un plug-in mucho mejor para resaltado de sintaxis. La diferencia básica es que este muestra los números de línea. Además, WP-Syntax fallaba al escapar los caracteres < y >.

¿Nos conocemos?

Un año y pico después de aquel entrañable “Hola mundo!” y con casi 80 entradas, este humilde bloggero te pide unos minutos para conocerte un poco mejor, querido lector ;-) Tus datos serán incluidos en un fichero automatizado en el que no se asociarán las respuestas con IP ni ubicación geográfica. Asimismo los datos acumulados serán utilizados con el único fin de mejorar este modesto blog. ¡Gracias por adelantado!

Relacionando enlaces en Delicious y contenidos en el blog

Enlazando enlaces en Delicious y contenidos en el blog

Hoy vamos a ver una aplicación experimental de eso que llaman “linked data”, una tendencia que podría considerarse web semántica, aunque sin ontologías ni estándares, sino basada en RSS, servicios web y API específicas para cada servicio: se trata de obtener enlaces en Delicious relacionados con los contenidos del blog.

Lo que hace este sencillo algoritmo es comparar las “nubes” de tags: obtiene los últimos enlaces de una cuenta de Delicious, comprueba que contengan las tags más recurrentes en el blog, y, cuanto más concurrentes sean las tags en el blog, más puntuación de afinidad se le da al enlace.

El ejemplo en acción lo puedes ver ahí a la derecha. Las tags más recurrentes del blog (web semántica, web social, evolución de internet…) están presentes en los enlaces.

El algoritmo puede ser útil para saber cómo evolucionan los intereses de redacción y navegación del blogger o aportar contenido añadido al blog. Estoy preparando más artículos con más criterios para evaluar la "cercanía temática" de los artículos, basándose en las etiquetas.

El código de abajo funciona sobre el gestor de contenidos de este sitio. Si a alguien le interesa hacer un plug-in para WordPress que soporte esta funcionalidad lo podemos intentar. Habría que adaptar la obtención de los datos (adaptando las sentencias SQL a la BD de WordPress o sustituyéndolas por llamadas a la API) y el modo de mostrarlos (sin Smarty).

Función para ordenar los enlaces

//Ordena una matriz por el valor de una de sus claves (primer nivel)

//TODO parece que no funciona bien

function array_sort_clave(&$data, $campo) {

  //Crea una función personalizada para el campo

  $codigo_funcion = “return strcmp($a['$campo'], $b['$campo']);”;

  usort($data, create_function(‘$a,$b’, $codigo_funcion));

  return $data;

}

Clase Enlace (la utilizo para los enlaces de Delicious y para el blogroll)

class Enlace {

  public $titulo;

  public $url;

  public $icono;

  public $rel;

  public $tags = array();

  

  public function __construct($titulo, $url, $icono, $rel=null, $tags=null) {

    $this->titulo = $titulo;

    $this->url = $url;

    $this->icono = $icono;

    $this->rel = $rel;

    $this->tags = $tags;

  }

}

La "chicha"

//Obtiene una nube de tags correspondiente a todos los post

static public function getTagcloudSimple() {

  $tagcloud = array();

  $cTags = BDConsulta("SELECT tag FROM tags WHERE post IN (SELECT id FROM posts ORDER BY creado DESC)");

  while ($tag = recorrer_resultados($cTags)) {

    $tagcloud[$tag['tag']]++;

  }

  return $tagcloud;

}

//Obtiene enlaces de Delicious, en orden de afinidad con el blog

//La afinidad con el blog se calcula a partir de las tags de los posts del blog. A cada enlace se le asigna un índice de afinidad

//El índice de afinidad se calcula sumando las veces que cada tag del enlace aparece en el blog

static public function getDelicious() {

  $enlaces = self::getEnlacesDelicious();

  $enlaces_con_puntos = array();

  $tags_blog = self::getTagcloudSimple();

  foreach ($enlaces as $enlace) {

    $puntos = 0;

    foreach ($enlace->tags as $tag_del_enlace) {

      $puntos += $tags_blog[$tag_del_enlace];

    }

    $enlaces_con_puntos[] = array('datos'=>$enlace, 'puntos'=>$puntos);

  }

  array_sort_clave($enlaces_con_puntos, "puntos");

  $enlaces_final = array();

  $cnt = count($enlaces_con_puntos);

  //Ordena inversamente la matriz, aunque ordena sólamente las claves

  for ($i=0; $i<$cnt; $i++) {

    $enlaces_final[$cnt-1-$i] = $enlaces_con_puntos[$i];

  }

  //Ordena el array según las nuevas claves. Vaya lío...

  ksort($enlaces_final);

  return $enlaces_final;

}

  

//Se procesa el RSS de los enlaces y se crea un array de objetos Enlace con él

static public function getEnlacesDelicious($limite=30) {

  if (!is_int($limite)) trigger_error("El parámetro debe ser un entero", E_USER_ERROR);

  //$xml = simplexml_load_file(RUTA_L . "delicious.xml");

  $xml = simplexml_load_file("http://feeds.delicious.com/v2/rss/isra00?count=$limite");

  $enlaces = array();

  foreach ($xml->channel->item as $item) {

    $tags_item = array();

    //No vale pasar $item->category directamente al constructor de Enlace, mejor pasarlo a array de cadenas

    foreach ($item->category as $s) {

      $tags_item[] = utf8_decode((string) $s);

    }

    $enlaces[] = new Enlace(utf8_decode($item->title), utf8_decode($item->link), null, null, $tags_item);

  }

  

  return $enlaces;

}

Mostramos los enlaces en una plantilla Smarty

<h3>Enlaces Delicious</h3>
<div id="blogroll" class="sb_seccion pq">

    <p>Mostrando enlaces relacionados con el blog. <a href="http://delicious.com/isra00/">Ver todos los enlaces</a>.</p>

    <ul>

    {foreach from=$delicious item=enlace name=i}{if $smarty.foreach.i.index < 10}

        <li>

            <a href="{$enlace.datos->url}">{$enlace.datos->titulo}</a>

            {foreach from=$enlace.datos->tags item=tag}

            <a class="insignificante" href="http://delicious.com/isra00/{$tag}">[{$tag}]</a>

            {/foreach}

            </li>

    {/if}{/foreach}

    </ul>

</div>

Nuevo por fuera, nuevo por dentro

Por culpa de la gripe que me ha mantenido en casa durante este puente (que encima, para mí ha sido de 5 días), aquí tienes el nuevo diseño del blog. Más sencillo, como todo lo bueno, más usable según las recomendaciones oficiales, fácil de leer para navegadores móviles y limitados, y ante todo, hecho por mí. Sin plantillas ni fotos de flipao a lo Enrique Dans. Un diseño centrado en el contenido y lo original que pueda aportar este humilde servidor.

Gracias al patrón Multivista, implementado según el método orientado a objetos que prometo explicar en breve, hay disponibles versiones RDF y RSS de casi todas las secciones. Además, he incluido un pequeño mod para visualizar la web sobre fondo negro, a gusto de los h4ckers del tres al cuarto y los ecologistas radicales, jeje.

Lo dicho, espero que os guste y tanto si es así como si no… comentarios aquí o en el twitter!

Experimentos en el blog

Sé que hacer experimentos cuando hay invitados no es de buen gusto, pero en este caso podemos aprender todos del experimento. Si habéis visitado el blog últimamente (no sólo a través de RSS), habréis notado la presencia de tres caralladas nuevas: los status Twitter de mis followers y míos, un widget de Google Friend y, más recientemente, los comentarios externalizados con Disqus.

Sobre Twitter poco que comentar: para gustos, colores. A veces lo uso y a veces no. Tenerlo en el blog me ayuda a extenderlo más alla de su misión original (publicar posts), para llegar a ser eso que denominan “Life streaming”. Aunque, por supuesto, lo central son los posts, ya que lo demás solo interesa a unos pocos.

Sobre Google Friend Connect diré tener un widget no me vale para nada, aunque la API no está mal. De todas maneras, los usuarios están más en Facebook que en GMail (con toda la información añadida que aporta), y por ello estoy haciendo pruebas con Facebook Connect. Es cierto que ambas son plataformas propietarias, pero OpenID y OAuth (ésta segunda me gusta más) están muy lejos de ser estándares de facto.

Y sobre Disqus… la verdad es que me cautivó la idea de “globalizar” las conversaciones generadas en el blog. Me parecía una idea muy buena de cara a la web semántica y al filtrado de información útil (me viene a la cabeza el mashup de comentarios que hizo Enrique Dans con Meneame y su blog). Me ahorro el almacenamiento de los comentarios, el CAPTCHA y tengo RSS de los comentarios sin esfuerzo. Pero si Disqus no añade tecnologías semánticas a su sistema, va a perder más de un usuario.