Blogs

migrar contenido de drupal a drupal con mysql y phpmyadmin

Atención: lo siguiente es una administración de Drupal de guerrilla. No os recomiendo llevarla a cabo a menos que realmente sepáis que lo necesitáis y sabéis lo que estáis haciendo. Igualmente, un backup antes de poneros en harina es altamente aconsejable. Si pierdes datos o la base de datos entera no me hago responsable de las consecuencias, lo que vas a leer a continuación es sólo apto para no cardíacos, y por tanto si sigues alguna de mis indicaciones lo haces por tu cuenta y riesgo :-).

Caso expuesto: migrar contenido de un drupal a otro, siendo el segundo un Drupal en marcha (más de 6.000 nodos y unos 1.000 usuarios) y el primero con unos 600 nodos y otros 500 usuarios aprox.

Primer paso, backup:

  • mysqldump --opt -uUSER -pPASS BBDDaMigrar  > BBDDaMigrar-BACKUP.sql
  • mysqldump --opt -uUSER -pPASS BBDDaMigrar  > BBDDaRecibirMigracion-BACKUP.sql

 

Segundo paso, migrar los nodos (del Drupal a migrar, se entiende):

  • CREATE TABLE node2 LIKE  node; #creamos una tabla sobre la que jugar
  • INSERT node2 SELECT * FROM node;

 

Repetimos con node_revisions:

  • CREATE TABLE node_revisions2 LIKE node_revisions;
  • INSERT node_revisions2 SELECT * FROM node_revisions;
  •  

Y con los tipos de contenido que tengamos a medida:


    • CREATE TABLE content_type_empresa2 LIKE content_type_empresa;
    • INSERT content_type_empresa2 SELECT * FROM content_type_empresa;

 

La tabla node_type no contiene nid ni datos de este tipo que tengamos que adaptar, solo una descripción por nombre del tipo de contenidos. Por lo tanto, no hace falta migrarla, simplemente nos aseguramos de que existe el tipo de contenido en la base de datos o el Drupal que va a recibir los nodos (page, blog, ... los estándar y cualquier tipo nuevo que hayamos creado nosotros o el admin del sitio).

Ahora volcamos estas tablas en el Drupal que vaya a recibir los datos:

primero, backup de las tablas:

  • mysqldump -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDOrigen node_revisions2 > node_revisions2.sql
  • mysqldump -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDOrigen node2 > node2.sql
  • mysqldump -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDOrigen node_revisions2 > node_revisions2.sql

 

segundo, volcamos el backup en el Drupal receptor.

  • mysql -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDDestino < node_revisions2.sql
  • mysql -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDDestino < node2.sql

Ahora tenemos los nodos en la base de datos final. Sin embargo los datos nuevos tienen ids que coincidirán con los que ya existan en Drupal (en el receptor, se entiende). Solución? Contar los nodos que ya existen y sumar ese número al nid de los nodos que hemos traido a la base de datos. Por ejemplo, en mi caso teníamos unos 6000 y pico nodos. El nid nuevo será 7.000 + nid.

No nos preocupamos por nada más ya que Drupal se encargará de asignar a los nuevos nodos los ids correctos, teniendo en cuenta los nuevos nodos que han aparecido en la base de datos.

Vamos allá:

  • UPDATE  `node2` SET  `nid` = `nid` + '7000';
  • UPDATE  `node_revisions2` SET  `vid` = `vid` + '7000';
    UPDATE  `node2` SET  `uid` = `uid` + '500'  ;

    • UPDATE  `node_revisions2` SET  `nid` = `nid` + '7000'  ;

      

idem con content_..._empresa, o los tipos de contenido que tengamos "a medida":

  • UPDATE  `content_type_empresa` SET  `nid` = `nid` + '7000';
  • UPDATE  `content_type_empresa` SET  `vid` = `vid` + '7000';
  • UPDATE  `content_type_empresa` SET  `uid` = `uid` + '500'  ;

 

cuidado con esto último. El nodo pertenece a un usuario de la BBDD anterior, con lo que también hay que, tanto en node, noderevisions y content, modificar el nuevo usuario.

Bien, en este punto ya estamos listos para volcar estas tablas en su sitio definitivo...o más bien para concatenar las tablas que ya tenemos con estas nuevas.

Primero, una vez más, backup de lo que tengamos:

 

  • mysqldump -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDOrigen node_revisions > node_revisions.sql
  • mysqldump -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDOrigen node > node.sql

 

Segundo, pasamos concatenamos los nuevos nodos, que es justamente el proceso inverso con el que empezamos todo este "lio":

 

    • INSERT node SELECT * FROM node2;
    • INSERT node_revisions SELECT * FROM node_revisions2;
    • INSERT content_type_X SELECT * FROM content_type_X2;

 

 

Y, si no ha habido ninguna incidencia, tenemos una bonita base de datos con el número de nodos total justamente igual a la suma de los nodos de ambas webs en Drupal, ni más ni menos, y con id's que son:

para la base de datos "receptora", los nid son los mismo,

para la base de datos que "aluniza" en esta base de datos, el nid que tuviera antes más la constante que hayamos elegido como precaución (en nuestro caso 7.000).

En otro post tocaremos el tema de las taxonomías, y cómo podemos migrarlas sin que se produzcan colisiones a la vez que los posts no pierdan sus respectivas clasificaciones.

Importar / Exportar de Drupal a Drupal usando SQL

En drupal hay un montón de módulos para realizar migraciones, como migrate, user_import, node_import... o incluso el fantástico Feeds, que te permite partir de casi cualquier fuente, como xml, cvs,... y fuentes tan difersas urls, ficheros, ...

Ahora bien, a veces es más sencillo, sabiendo un poco de sql y organizandose uno mismo la migración, hacerlo directamente a mano. Es el caso de una migración, una importación más bien de usuarios de un Drupal a otro. No me preguntéis como me he metido en tal lio, pero a veces pasa... "shit happens" decía un amigo.

Y, como decía otro amigo... que demonios, los hombres de verdad programan en C a "pelo" y con vi sin plugins ni mari*** de esas :-).

Vamos allá:

i) Pasar tablas:

  • CREATE TABLE users2 LIKE users;
  • INSERT users2 SELECT * FROM users;

 

Actualizamos el uid para que no "choque" con el de la base de datos en la que vamos a volcarlo:

  • UPDATE  `users2` SET  `uid` = `uid` + '500'  ;

 

Esto suma 500 a todos los uid que existan (no hay where ni limit, con lo que la consulta se hace para todas las tablas y no se pone limitación.

En mi caso el número de usuarios era de 400 y pico, casi 500. En vuestra tabla tendréis que comprobar el último uid y cambiar la cifra. Da igual cuál usemos puesto que Drupal usa autoincrement, con lo que mientras no solapemos uids, drupal "cazará" la última que exista (1000 y pico en mi caso) y continuará trabajando desde ahí.

Ahora hacemos backup SOLO de la tabla: 

  • mysqldump -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDOrigen users2 > users2.sql

 

y nos la llevamos a la otra base de datos

 

  • mysql -uUSUARIOMYSQL -pPASSMYSQL nombreBBDDDestino < users2.sql

 

Excelente. Ya tenemos la base de datos con las dos tablas juntas (origen y destino) y con los uids incrementados de forma que no se solapen entre ellos. No habría problema si no lo hemos hecho bien porque al hacer el import mysql se "quejaría" de que ya existe un dato con ese uid (que debe ser único).

Ahora hacemos justo lo contrario de lo que habíamos hecho al inicio:

 

  • INSERT users SELECT * FROM users2;

 

con lo que la nueva tabla pasará a la tabla users... y drupal ni se habrá dado cuenta :-).

 

Huelga decir que este procedimiento puede aplicarse a cualquier tabla, por ejemplo a la tabla node, donde residen los nodos, la tabla content_TIPOCONTENIDO, donde residen los contenidos de CCK, ...

Notas:

Hay otra forma de crear la tabla users2 más rápida, que es la siguiente:

create table users2 select * from users;

De esta forma genera la tabla users2 e importa de una todos los datos de users.

categorias: 

eliminar una base de datos en Symfony2 / Doctrine2

eliminamos el php que contiene la definición de la tabla actual, por ejemplo:

rm src/CruiseHunter/CrucerosBundle/Entity/Crucero.php

Ejecutamos el comando:

sudo php app/console doctrine:schema:drop --force

Mas información:

http://www.doctrine-project.org/docs/orm/2.0/en/reference/tools.html sobre todo la sección 23.1.4. Command Overview

 

Y ya estamos en condiciones de volver a ejecutar:

sudo php app/console doctrine:schema:update --force

sin que nos de un error porque exista ya la clase, lo que suele indicar que hay un .php en Entities que no debería...

Drupal: Publicar un banner o mensaje despues del primer (o segudo) post

Seguro que te ha ocurrido alguna vez. Tienes un banner o un determinado mensaje que quieres colocar en el teaser, después del primer o segundo post, pero no más. No quieres que se repita de forma indefinida, sobre todo porque queda muy intrusivo.

La solución? Mas fácil de lo que en principio había estado tratando de hacer. Si usamos una variable global, su contenido se va a mantener a lo largo de todo el ciclo de vida de carga de la web (mientras un usuario abre la página). Por ejemplo:

<?php

global $nodenumber;

if($teaser){

//if(drupal_is_front_page()){

 

Fijaos que lo pongo al principio del fichero, justo antes de la declaración de inicio del $teaser de Drupal. De esta forma la varible ya está inicializada y evitamos que cada vez que vaya a mostrarse un post en la misma página se reinicie de nuevo la varible.

Ahora vamos al final de la plantilla del tipo de contenido, y hacemos lo siguiente:

<?php //print_r ($node); 

echo 'page:: ' . $page;

$nodenumber = $nodenumber + 1;

echo $nodenumber;

if($nodenumber == 1 || $nodenumber == 3) {

?>

<a href="http://bit.ly/sBPXWg"><img src="<?php echo base_path() . path_to_theme()?>/imagenes/BANNER.jpg" alt="" ></a>

<?php

}

?>

 

Facil, verdad? En nuestro caso estamos mostrando la imagen después del post número 1 y del tercero.

El código tendremos que insertarla en la plantilla del tipo de contenido que estamos usando, por ejemplo en node-blog.tpl.php, o en node-TIPOCONTENIDO.tpl.php

Programadores Drupal

Somos una pequeña empresa / freelance especializados en la programacion web, y en especial somos entusiastas del mundo Open Source, especialistas programadores en Drupal y recientemente podemos ponernos la etiqueta de programadores Symfony2, un grandísimo framework php con muchísimo futuro.

En realidad cualquier proyecto en php está dentro de nuestras capacidades, como lo sería cualquier programador o ingeniero sería capaz de adaptarse en poco más de una semana a cualquier lenguaje de programación nuevo (no es ninguna brabuconada, todos los lenguajes comparten estructuras y grandísimas similitudes, sólo se diferencian en "pequeñas" cosas).

Nos gusta pensar que ayudamos a empresas y emprendedores a plasmar sus sueños sobre la pantalla, y nosotros mismos lanzamos y mantenemos nuestros propios sueños online. Nos encanta la programacion web, el desarrollo y la programación con herramientas "lógicas" como Drupal o lenguajes de programación elegantes como Symfony, Symfony2, Ruby on Rails y en general casi cualquier cosa con la que podamos transformar ideas en "sueños en movimiento".

Si necesita nuestra ayuda y puede encontrarnos, quizá pueda contratarnos...

Bases de datos en Symfony2: Doctrine2

Me encanta aprender lenguajes nuevos y tecnologías nuevas a pesar de lo desesperante de algunos momentos en los que te encuentras atascado. Es el caso.

Trabajar con Bases de datos en Symfony2 es sencillo, casi divertido. Si ya tenemos creado el Bundle es tan fácil como lo siguiente (si no lo tenemos creado os recomiendo leer el primer post de este tutorial sobre symfony2, Hola Mundo en Symfony2, una pista: php app/console generate:bundle --namespace=Acme/StoreBundle)

Lo siguiente es asegurarnos de que los datos de configuración de nuestra base de datos son correctos (tipo de base de datos, password, puerto, ...). Si hemos seguido los pasos de instalación correctamente, lo más normal es que ya esté configurada, y el fichero app/config/parameters.ini contiene esos datos.

(i) Normalmente lo primero es crear una base de datos sobre la que podamos trabajar. En Symfony2 no es necesario, el propio framework puede hacerlo por nosotros:

php app/console doctrine:database:create

Ojo con los permisos, en ubuntu probablemente deberemos usar el comando "sudo" antes del comando anterior para poder ejecutarlo con permisos de superusuario.

(ii) Lo siguiente es crear una estructura para nuestra base de datos. Antes de ponernos a picar código es importante diseñar bien la aplicación, independientemente del lenguaje, framework o "bicho" que estemos usando para plasmar nuestros sueños sobre la pantalla.

En Symfony vamos a pensar en Entidades. Una entidad es básicamente una representación de un objeto de nuestra base de datos. Por ejemplo, si tenemos una tienda o un ecommerce, una entidad sería un producto, o un crucero por ejemplo si nos dedicamos al turismo. Así, la entidad sería Producto.php y Crucero.php respectivamente.

Una vez tengamos clara la estructura vamos a crear un directorio nuevo dentro del directorio de nuestra app src/NombredenuestraApp/NombredelBundle/Entity/Objeto.php

Por ejemplo: src/CruiseHunter/CrucerosBundle/Entity/Cruceros.php

El fichero seguirá este formato:

----------------------------------------------

 

<?php

// src/Acme/StoreBundle/Entity/Product.php

namespace CruiseHunter\CrucerosBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**

 * @ORM\Table(name="cruceros")

 * @ORM\Entity

 */

class Crucero

{

    /**

     * @ORM\Id

     * @ORM\Column(type="integer")

     * @ORM\GeneratedValue(strategy="AUTO")

     */

    protected $id;

    /**

     * @ORM\Column(type="string", length=100)

     */

    protected $nombre;

    /**

     * @ORM\Column(type="integer")

     */

    protected $precio;

    /**

     * @ORM\Column(type="string", length=100)

     */

    protected $descripcion;

}

----------------------------------------------

 

Una vez en este punto, quedaría plasmar esta estructura en nuestra base de datos. Pero, un momento, hasta ahora no hemos tenido que tirar del comando mysql ni tan siquiera abrir phpmyadmin... no será esta una excepción:

sudo php app/console doctrine:generate:entities CruiseHunter/CrucerosBundle/Entity/Crucero

Con esto acabamos de crear las Entidades, que se usarán, entre otras cosas, para crear las tablas que vamos a necesitar en la base de datos.

Cuidado con repetir este último comando porque nos dará un error de redeclaración de la clase Crucero (o la que sea en tu caso) y tendremos un problema ( soy un poco manazas, lo se :-( ).

(iii) Bueno, allá vamos:

sudo php app/console doctrine:schema:update --force

y tendremos una respuesta parecida a esto:

 

Updating database schema...

Database schema updated successfully! "1" queries were executed

 

Si todo ha ido bien, ahora tenemos unas bonitas tablas nuevas en nuestra base de datos reflejando esta estructura. Fácil, verdad? :-)

 

Veamos, error clásico, olvidar el <?php del inicio del documento. Resultado? Este:

 

  [RuntimeException]                                                                            

  Namespace "CruiseHunter\CrucerosBundle\Entity\Crucero" does not contain any mapped entities.  

 

Si nos encontramos con este dichoso error no os paséis horas y horas como yo buscando la solución. Lo más obvio, lo que nadie te dice al principio, olvida los config, routing, kernel, etc, etc... Fíjate si has olvidado el puñe***o <?php de declaración de inicio de un fichero php. Ale, de nada :-).

En el siguiente capítulo veremos como acceder a los datos almacenados en la base de datos.

Tutorial de Symfony2: Hola mundo en Symfony

Una vez tenemos instalado Symfony2 en nuestro servidor (algo sencillo como vimos en el capítulo anterior) vamos a comenzar a trabajar.

(i) En primer lugar tenemos que crear un bundle, que básicamente es la semilla de nuestra aplicación, el germen de lo que vamos a construir.

php app/console generate:bundle --namespace=Acme/HelloBundle --format=yml

Básicamente le estamos indicando a Symfony2, crea un Bundle, cuyo formato es yml y al que le vamos a dar el nombre de Hello (HelloBundle en terminología Symfony2) dentro del entorno Acme.

(ii) Vamos a crear el clásico "Hola Mundo" que todo hijo de vecino crea cuando está aprendiendo un nuevo lenguaje de programación. Para ello iremos al fichero /app/config/routing.yml dentro de nuestra aplicación:

 

  • hola:  
  • pattern:  /hola/{name}
  • defaults: { _controller: AcmeHelloBundle:Hello:index }

 

 

Aquí hay que llevar especial cuidado en no meter tabuladores en lugar de espacios, ya que Symfony lo detectará como un error y podemos volvernos locos buscando qué es lo que hemos hecho mal.

Un pequeño truco es usar un default, un valor por defecto para {name}. De esta forma estamos creando también una página para el "root" o directorio raíz:

  • hola:  
  • pattern:  /hola/
  • defaults: { _controller: AcmeHelloBundle:Hello:index , name:Mundo}

 

 

El default es "name:Mundo", separado por una coma.

Si intentamos ahora mismo acceder a nuestro servidor recibiremos un error muy específico y claro: nos falta un controlador.

localhost/DIRECTORIO-SYMFONY2/web/app_dev.php/hola/mundo

 

(iii) Nada más sencillo de solucionar. Creamos un fichero que se llamará, teniendo en cuenta cómo hemos llamado el Bundle, de la siguiente forma:

// src/Acme/HelloBundle/Controller/HelloController.php

namespace Acme\HelloBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class HelloController{

    public function indexAction($name)    {

       return new Response('<html><body>Hello '.$name.'!</body></html>');  

 }

}

 

Dentro de HelloController.php hay dos declaraciones fundamentales, la clase HelloController, en la linea 4: class HelloController{

y la función indexAction, una línea más abajo. A esta función hemos hecho referencia desde el routing.yml, justamente en la linea que habla del controller:


  • defaults: { _controller: AcmeHelloBundle:Hello:index , name:Mundo}

En realidad le estamos dando la ruta al Bundle, AcmeHello, y al Action que vamos a ejecutar: index. Ambos, Bundle y Action llevarán el postfijo después de su nombre, es decir, AcmeHelloBundle e indexAction. Si por ejemplo el action se llamara NuevoCliente, la función en el controller se llamaría NuevoClienteAction, y haríamos referencia a ella desde el fichero yml (pronunciado "YAMEL") de esta forma:


 

  • defaults: { _controller: AcmeHelloBundle:Hello:NuevoCliente}

 

 

Tutorial de Symfony2: instalacion

1. Descargamos symfony2: http://symfony.com/download

2. Descomprimimos y dejamos en un directorio dentro de nuestro apache, por ejemplo:

/var/www/symfonylabs/

3. Si entramos en /var/www/symfonylabs/web nos dará error. Tenemos que entrar a configurarlo primero: http://localhost/symlabs/web/config.php

Y seguimos los pasos para configurarlo

4. Seguramente no podamos escribir sobre el fichero parameters.ini, con lo que lo abrimos y pegamos el codigo que nos indicará el propio "wizard" o configurador que estamos siguiendo: http://localhost/symlabs/web/app_dev.php/

Listo, ya podemos acceder a nuestra nueva app:

http://localhost/symlabs/cruisehunter/web/app_dev.php/

Fácil, verdad? En el siguiente punto aprenderemos a crear la primera aplicación o librería (llamada Bundle en Symfony2) y a "picar" algo de código.

Recuperar o resetear una contraseña en Drupal 7

Le llaman la navaja suiza del Drupal. Y es verdad que una vez te acostumbras a usarlo no puedes dejar de hacerlo.

Lo mejor de todo es que te puede sacar de un apuro. Os pongo en situación. Drupal7 instalado en local, sendmail no funciona bien, y la password de administrador la he perdido. Mal momento para ponerme a buscar que le pasa al sendmail... solución? En drupal 6 es fácil, vamos a mysql o a phpmyadmin y ejecutamos:

UPDATE users SET pass = MD5('mynewpassword') WHERE uid = 1;

ahora bien, en Drupal7 la cosa no es tan sencilla.

Vamos a instalar Drushhttp://drupal.org/project/drush

muy sencillo, ejecutamos en consola:

  • pear channel-discover pear.drush.org
  • pear install drush/drush

 

Si no tenemos instalado pear, hacemos lo propio:

apt-get install pear-php

y, una vez todo en su sitio, sólo nos queda cambiar la password al usuario que queramos:

drush user-password USUARIO --password="NUEVAPASSWORD"

Obviamente cambiamos USUARIO por el nombre de usuario, y NUEVAPASSWORD por la password que queramos. A partir de aquí podemos volver a loguearnos en nuestra web con las password que acabamos de definir.

Otra opción, más rápida, sería especificar una password con mysql concreta para entrar con el usuario y cambiarla. Por ejemplo "password":

UPDATE users SET pass='$S$Cd059Vsxc8berFeg6hspaa7ejx2bSxyUisvCbT4h9o8XIgSUtPKz' WHERE uid=1;

Visto en: http://chillburn.com.au/blog/changing-resetting-the-admin-password-in-drupal-7/

Programadores vs Usuarios

Un poquito de humor para aguantar lo que queda de semana con una sonrisa ;-).

Visto en http://rafuru.blogspot.com

categorias: