Iniciador Barcelona de mayo con Joaquin Cuenca, fundador de Panoramio
admin — Lun, 14/05/2012 - 10:51
Mañana martes vuelve Iniciador a la hora de siempre, 19h, con Joaquin Cuenca, fundador de Panoramio que nos explicará cómo crear una compañía en la que google esté interesado para comprarla.
Tenéis más info en el post de Iniciador.
SeedRocket Weekend
admin — Mié, 25/04/2012 - 11:09
Los próximos 5 y 6 de mayo se hará el Seedrocket Weekend.
Si no conoces Seedrocket te diré que es una aceleradora de proyectos. Dos veces al año, una vez en Barcelona y otra en Madrid, se realiza una especie de competición en los que los 12 mejores proyectos presentados pasan una semana junto a los mentores de seedrocket (emprendedores de éxito) para ayudar a mejorar y enfocar los proyectos.
Una vez finalizada esa semana los mentores votan por los 3 mejores proyectos y se invierte 120.000€ repartidos entre los tres. Debido a la gran reputación del Seedrocket es mucho más fácil conseguir luego una segunda ronda de financiación si el proyecto demuestra una buena progresión.
Nosotros con Edukame nos vamos a presentar pero sabemos que la competición es muy dura así que habrá que tener algo de suerte. Hay más concursos de este tipo pero el SeedRocket es al que más ganas tenemos de entrar.
Todo esto viene para comentar que SeedRocket organiza un fin de semana en el que quien tenga una idea la propone, se hacen equipos, cada uno se apunta a la idea que más le gusta y se desarrolla un prototipo. Es un fin de semana intensivo pero podrás salir de él con un equipo y con una idea desarrollada. Y el mejor proyecto tendrá una entrada de oyente para el campus de Seedrocket.
Yo si no estuviese ya con una idea y un equipo estupendo no me lo pensaría dos veces. Como la cosa tiene sus gastos hay que pegar una pequeña entrada pero merece la pena. Y si vais de parte de Iniciador os hacen un descuento poniendo como código de cupón INICIADOR.
Iniciador de abril con Escapada Rural: Claves de éxito para un modelo de negocio freemium de clasificados
admin — Jue, 19/04/2012 - 10:06
El martes que viene día 24 de abril vuelve Iniciador y en esta ocasión me hace especial ilusión porque contaremos con Gus Bertolo y Fabio Nuñez, socios fundadores de Escapada Rural. Y me hace ilusión porque ellos venían a Iniciador desde los principios de Iniciador y ahora ya han progresado tanto que pueden venir a darnos una charla.
Además Escapada Rural son unos de los primeros ganadores del Seedrocket, algo que intentaremos emular con Edukame.com.
Hablaremos de los tiempos que son necesarios para madurar un negocio en este sector. Hablaremos de la apuesta que en su día tomaron Gus y Fabio, dadas las características de este mercado en España, con una competencia líder muy firme (Top Rural) y su estrategia de modelo freemium.
Más info en la web de Iniciador.
Multi IVA con Drupal Commerce
admin — Mar, 10/04/2012 - 10:39
Si tenéis una tienda en la que todos los productos sólo tienen un IVA la configuración será realmente fácil en Drupal Commerce. Tan sólo tenéis que crear un impuesto tipo VAT y listo. Se aplicará para todos los productos y se especificará en en el checkout. Además podréis elegir si ponéis el precio con IVA en el producto o si lo hacéis sin IVA y Drupal Commerce lo ha de añadir al mostrarlo.
En cambio si queremos tener productos que tenga diferentes IVA's la cosa no es tan sencilla aunque en 10 minutos lo tendremos hecho. Seguramente hay diferentes formas de hacerlo pero yo lo he hecho así:
Actualización
Lo había puesto usando una categoría y el módulo Commerce Extra Rules Conditions con la condición "Line item product has term" pero gracias a Pedro Cambra me ha enseñado una mejor opción que es la que voy a explicar ahora.
Primero de todo hemos de asignarle al "product" un campo tipo select texto o entero que pueda tener nuestros posibles valores del iva.
Luego los IVA's necesarios en la configuración de taxes de Drupal Commerce, en mi caso he creado los tres, 18%, 8% y 4%. Con esto conseguimos que todos los productos tengan todos los IVA's así que hemos de hacer algo para aplicar los IVA's selectivamente. Para eso vamos a "configure component" en la configuración de uno de ellos. Allí hemos de poner una condición para que sólo se aplique a los productos que nosotros queramos.
Lo primero de todo es añadir la condición "Entity has field", en data selector poner "commerce-line-item" y en campo "commerce_product".
Luego volvemos a añadir "Entity has field", en data selector "commerce-line-item:commerce-product" y en el campo "field_iva".
Ahora ya podemos comprar el campo iva con el IVA que queremos aplicar en esta regla. Pongamos que es la regla del iva del 18%. Añadimos una nueva condición de "Data comparison" y como "data to compare" "buscamos commerce-line-item:commerce-product:field-iva". Lo puedes poner así directamente o irlo buscando poniendo primero commerce-line-item esperando al autocompletado hasta que salga commerce-product y luego lo mismo para field-iva (en mi caso he llamado así al campo pero tú lo puedes haber llamado diferente)
Ahora sólo falta hacer lo mismo con los otros IVA's y asignamos a cada producto el valor su iva en el campo iva.
Migrar de wordpress a Drupal con Feeds
admin — Jue, 05/04/2012 - 22:02
Tal como comenté en el post del Proyecto Edukame la primera fase era exportar los contenidos que tenemos ahora en Wordpress a Drupal 7.
Para esto en Drupal 7 existen varias alternativas:
- Wordpress Migrate: Usando el módulo Migrate más el Wordpress Migrate puedes importar posts, usuarios, comentarios, attachments y páginas. Si lo hace todo bien es realmente bueno y recomendable ya que requiere muy poca configuración.
Desgraciadamente en mi caso todo fue mal. Muchos errores, y sobretodo comportamiento errático. A veces funcionaba casi bien, a veces muy mal. Así que después de estrellarme muchas horas con esto decidí probar otra cosa. Tal vez a ti te funcione bien y simplemente sea que no supe configurarlo.
- Módulo de 0: Otra opción es crear un módulo que lea un XML y que vaya guardando los nodos y los comentarios. No debería ser muy complicado pero para procesos largos como una importación habría que usar algo especial para que no nos de un timeout, tipo el batch API. Me lo estuve replanteando pero antes quise probar otras cosas que ya tuviesen en cuenta estas cosas. Además esta solución no permite "volver atrás", algo que siempre pasa cuando estamos configurandolo porque nunca funciona a la primera.
- Otros: Pues eso, otros, que seguro que existen y que yo desconozca o no haya tenido en cuenta
- Feeds: Lo que al final he usado y me ha ido bastante bien, aunque como todo tiene sus problemillas. A continuación explicaré como hacer una migración de wordpress a Drupal usando Feeds.
Antes de todo hemos de conseguir los datos de wordpress y como vamos a usar Feeds lo idea sería tener un XML aunque a feeds se le puede alimentar en un montón de formatos. Así que hemos de ir a wordpress y en la barra de herramientas, vamos a Exportar.
Allí le damos a exportar todo y nos devolvera un archivo WXR, que es un XML.
Una vez con el WXR es recomendable partirlo y tener uno de ejemplo con muy pocos posts, que lo podemos hacer simplemente editandolo.
Después de esto nos bajamos Feeds, Feeds XPath Parser, Feeds Tamper, Media Feeds y Feeds Comment Processor.
Luego los activamos tal como se ve en esta captura (y dónde también podéis ver las versiones que he usado)
En esta captura está activado el Feeds Comment Processor pero os aconsejo desactivarlo junto a los comentarios por un error que me salió a importar los post. No guardé el error y ahora no lo encuentro. Si lo hacéis así lo único que os pasará es que luego habrá que activar los comentarios en todos los nodos importados pero ya os pongo luego como.
Una vez esto en el tipo de contenido dónde pondemos los post hemos de crear los campos de media para las imágenes (puedes ser un campo imagen, se haría todo igual), uno para los tags, otro para las categorías, otro para los nids de wordpress y otro para la url antigua de wordpress.
Después hemos de ir a Feeds Importers en Estructura (admin/structure/feeds/wordpress_import) y crear uno nuevo que llamaremos Wordpress Import (por ejemplo). Lo pondremos para que no haga ninguna importación periódica, que esté en un formulario sólo y que comience la importación al mandarlo. Si nuestro XML es muy grande (el mío eran sólo 750 posts) le ponemos que lo procese en background o aumentamos timeout de php. Yo por si acaso, sobretodo después de ciertos errores le aumenté todas estas variables (en la configuración de apache o en el .htaccess). Recuerda volver a la normalidad una vez hayas hecho el proceso.
php_value max_execution_time 3000
php_value max_input_time 6000
php_value upload_max_filesize 50M
php_value post_max_size 50M
php_value memory_limit 256M
En Recuperador o Fetcher lo podemos dejar en HTTP o File Upload, da bastante igual.
En el Parser hemos de poner el XPath
En processor hemos de poner el node processor:
Y en las opciones del node processor hemos de poner el formato de texto en full html o configurar el filtered html para permitir los tags que nosotros queramos, pero por experiencia es mejor ponerlo en full html. Se supone que confiamos en el contenido que estamos exportando. Es recomendable instalar el módulo Wysiwyg linebreaks para que se mantengan los artículos que sin < p >'s tienen saltos de línea como separador de párrafos.
Hemos de asegurarnos que no expire y asignar los posts importados al tipo de contenido correcto, el resto de opciones no es importante si sólo estamos importando y no vamos a actualizar.
En el mapping del node processor lo que hemos de hacer ir añadiendo el origen (una expresión de XPath) de los datos al target. He añadido un unique target porque sino, y no sé muy bien porqué, me creaba nodos duplicados.
Ya casi terminando, hemos de configurar las opciones del XPath XML Parser. Para quien no sepa que es XPath se puede mirar este documento que es el que usé yo para saber cómo funciona. Es una manera fácil y potente de seleccionar los campos de un fichero XML, como si fuera un selector en CSS.
Ya sólo nos falta configurar el Feeds Tamper que tiene su intríngulis. El Feeds Tamper nos sirve para hacer transformaciones a los valores antes de guardarlos. Por ejemplo, podemos quitar espacios al principio y al final de un texto, podemos pasar a mayúsculas, reemplazar un texto por otro o simplemente quitar un string.
En nuestro caso necesitamos cambiar un nombre por un id de usuario, necesitamos extraer las imágenes del texto para pasarlas al field media y necesitamos quitarle para la url el http y el dominio. Para lo último podemos usar uno de los plugins de tamper, el "Finde Replace".
Pero para las otras dos cosas no encontré un plugin que me fuera bien. Bueno, podría haber usado una expresión regular para extraer las imágenes pero al final decidí que era más potente y flexible usar el PHP Simple HTML DOM Parser. Sobretodo por que es tolerante a html mal formados, no como una expresión regular que a no ser que sea hipersupercompleja no tiene en cuenta que esté mal escrito el tag de imagen.
Para poder añadir plugins al Feeds Tamper es relativamente fácil. Hemos de usar en un módulo el hook_ctools_plugin_directory:
/** * Implements hook_ctools_plugin_directory(). */ function edukame_module_ctools_plugin_directory($module, $plugin) { if ($module == 'feeds_tamper') { return 'plugins'; } }
plugins es el nombre del directorio dónde ponemos los ficheros que definen cada plugin, el cual ha de estar en el mismo directorio que el módulo dónde lo hemos definido. En este caso yo lo he puesto dentro del módulo edukame_module.
Ahora, ¿como son los ficheros de los plugins? Pues aquí os pongo un par de ejemplos:
El que nos transforma los nombres de usuario de wordpress a uids (previamente hemos tenido que crear esos usuarios, con el mismo nombre de usuario que en wordpress)
wordpress_id.inc
(este lo usaremos para los comentarios)
$plugin = array( 'form' => 'feeds_tamper_wordpress_id_form', 'callback' => 'feeds_tamper_wordpress_id_callback', 'validate' => 'feeds_tamper_wordpress_id_validate', 'name' => 'Wordpress id', 'multi' => 'direct', 'category' => 'Text', ); function feeds_tamper_wordpress_id_form($importer, $element_key, $settings) { $form = array(); return $form; } function feeds_tamper_wordpress_id_validate(&$settings) { } function feeds_tamper_wordpress_id_callback($result, $item_key, $element_key, &$field, $settings) { $query = new EntityFieldQuery(); $query ->entityCondition('entity_type', 'node') ->propertyOrderBy('created', 'DESC') ->fieldCondition('field_old_nid', 'value', array($field)) ->range(0,1); $result = $query->execute(); $nids = array_keys($result['node']); $field = array_pop($nids); }
user_import.inc
$plugin = array( 'form' => 'feeds_tamper_user_import_form', 'callback' => 'feeds_tamper_user_import_callback', 'validate' => 'feeds_tamper_user_import_validate', 'name' => 'User Import', 'multi' => 'direct', 'category' => 'Text', ); function feeds_tamper_user_import_form($importer, $element_key, $settings) { $form = array(); return $form; } function feeds_tamper_user_import_validate(&$settings) { } function feeds_tamper_user_import_callback($result, $item_key, $element_key, &$field, $settings) { $owner = user_load_by_name($field); $field = $owner->uid; }
image_extractor.inc
$plugin = array( 'form' => 'feeds_tamper_image_extractor_form', 'callback' => 'feeds_tamper_image_extractor_callback', 'validate' => 'feeds_tamper_image_extractor_validate', 'name' => 'Image extractor', 'multi' => 'direct', 'category' => 'Text', ); function feeds_tamper_image_extractor_form($importer, $element_key, $settings) { $form = array(); return $form; } function feeds_tamper_image_extractor_validate(&$settings) { } function feeds_tamper_image_extractor_callback($result, $item_key, $element_key, &$field, $settings) { include_once(DRUPAL_ROOT . base_path() . drupal_get_path('module','edukame_module') . '/simplehtmldom_1_5/simple_html_dom.php'); $images = array(); $post_dom = str_get_html($field); if($post_dom && is_object($post_dom) && isset($post_dom->nodes)){ $img_tags = $post_dom->find('img'); foreach($img_tags as $image) { if (module_exists('transliteration')) { $image->src = transliteration_get($image->src); } $images[] = $image->src; } } $field = $images; }
Para este último has de tener en cuenta que yo puse el simplehtmldom dentro de la carpeta del módulo edukame, en la misma carpeta que están los plugins.
Entonces si vamos a las opciones de Tamper han de salir activados los plugins tal que así:
La url la hemos guardado para tener las mismas url's que en wordpress, así que nos falta configurar el pathauto para que pille el campo url. Nos vamos a configuración, alias de url y finalmente patters y ponemos:
Sólo os tenéis que fijar en la url del tipo de contenido artículo o el que hayáis escogido vosotros.
Antes de finalizar es totalmente recomendable hacer un backup de la base de datos ya que aunque Feeds nos permite volver atrás y borrar los nodos esto no siempre funciona si la importación fue realmente mal.
Para hacer un backup puedes usar el módulo Backup and Migrate o una sencilla sentencia de drush:
drush sql-dump > exportacion-configurado-feeds.sql
Ahora sólo nos falta ir a /import, escoger el wordpress import, poner la url del xml (o subirlo, dependiendo de cómo lo hayamos configurado) y esperar. Lo siento, seguramente habrá ido mal.
Posibles errores que te pueden pasar y que a mi me pasaron:
This page contains the following errors:
error on line 49832 at column 16: Opening and ending tag mismatch: encoded line 0 and script
Below is a rendering of the page up to the first error.
Esto me pasó porque el xml estaba mal formado, en mi caso era porque en algunas páginas teníamos código javascript y wordpress al exportar no lo mete bien dentro de un CDATA, o se lo pone dos veces, no recuerdo exactamente. Pero lo importante para resolver este problema es ver el archivo con Firefox porque te indicará la línea dónde está el problema. Vas a esa línea y lo editas para solucionarlo.
Mayúsculas: Este es un error realmente curioso, si tienes dos ficheros (imágenes por ejemplo) que se llaman igual pero se diferencian en las mayúsculas, imagen.jpg Imagen.jpg, entonces te dirá que está duplicado.
Es un bug del core: http://drupal.org/node/966210
¿Qué solución tiene esto? Pues o esperar a que lo arreglen o si no son muchos cambiarlos a mano, que es lo que hice yo.
Caracteres UTF en las url's (ñ's, acentos): Otro de esos bugs tan guays del core aunque yo lo puse en media_internet http://drupal.org/node/1492658
Si subes una imagen con ñ's o acentos, por ejemplo, el módulo transliterate lo hace genial pero en cambio si la añades desde una url no lo hace bien.
Mi solución para esto fue hacer una copia en el mismo directorio de los archivos culpables quitándoles los caracteres "raros". Así no tuve que modificar los posts en wordpress y sólo tuve que hacer un transliteration en el plugin dónde extraía las imágenes.
Esto no sé muy bien porqué era, pero me pasaba al poner el xml entero. Lo que hice para minimizar el problema fue exportar el archivo por autores y así tener ficheros más pequeños y problemas más localizados. Esto puede que no sea una opción para ti, entonces mira a ver si alguien ha contestado este bug: http://drupal.org/node/1508154
Los comentarios
Ahora sólo nos falta importar los comentarios, lo cual después de todo lo otro es casi pan comido. Activamos los módulos comments y Feeds Comment Processor. Creamos un nuevo feed importer, le asignamos como processor el comment processor:
Configuramos el mapping:
Y configuramos el XPath
Finalmente sólo queda activar el plugin de tamper wordpress id para convertir los id's de wordpress en id's de drupal:
Ahora volvemos a crear un backup de la base de datos, vamos al formulario de importación, ponemos otra vez el XML entero y esperamos...uppss, volvió a ir mal?
Errores que me encontré yo:
Cuando el módulo feeds_comment_processor añade los comentarios lo hace en el orden en el que aparecen. La exportación de wordpress sí exporta el comment_ID pero esto Drupal no lo usa y wordpress los exporta en el orden que le da la gana. Para solucionar esto es más fácil modificar wordpress, es tan sólo una línea.
También te puede pasar que te un error de sql y te diga que el nombre es demasiado largo (creo que son 256) con lo cual te puedes preguntar. ¿Quien ha puesto un nombre así de largo? Y la respuesta es que son los pingbacks así que lo que yo hice fue quitarlos porque tampoco me interesaban.
Para eliminar pingbacks y ordenar los comentarios has de ir a la línea 403 del archivo wp-admin/includes/export.php y dejarlo así:
<?php $comments = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam' AND comment_type <> 'pingback' ORDER BY comment_ID ASC", $post->ID ) );
Finalmente si teníamos desactivados los comentarios al importar los posts nos encontraremos que no tendremos activados los comentarios en todos nuestros nodos importados. Para no tenerlos que hacer manualmente podemos hacer:
UPDATE node SET comment = 1 WHERE type = 'article'
UPDATE node_revision LEFT JOIN node ON node.nid = node_revision.nid SET node_revision.comment = 2 WHERE node.type = 'article'
Esto se puede hacer desde drush asi:
drush sqlq "UPDATE node SET comment = 1 WHERE type = 'article'"
drush sqlq "UPDATE node_revision LEFT JOIN node ON node.nid = node_revision.nid SET node_revision.comment = 2 WHERE node.type = 'article'"
Y ufff...creo que esto es todo. Seguramente con un post tan largo me habré olvidado de cosas, otras estarán mal y seguramente os saldrán problemas nuevos que a mi no me pasaron. De todas maneras espero que sea una guía muy útil para que al menos os tengáis que pelear menos de lo que lo tuve que hacer yo.
El próximo paso será importar los productos de una tienda con Drupal 6 + Ubercart a Drupal 7 con Drupal Commerce.
Comentarios recientes
hace 3 años 6 semanas
hace 3 años 39 semanas
hace 3 años 47 semanas
hace 4 años 3 días
hace 4 años 8 semanas
hace 4 años 8 semanas
hace 4 años 9 semanas
hace 4 años 10 semanas
hace 4 años 10 semanas
hace 4 años 11 semanas