Drupal Hacking

Da Wizard linux team wiki.

Jump to: navigation, search


Contents

Migrare Utenti e Forum da VBULLETTIN a Drupal 5.1

Salve ora vi illustrerò in quale modo abbiamo migrato il forum del VBULLETTIN a quello di DRUPAL 5.1. La guida presuppone che sappiate usare il linguaggio SQL e l'utility PHPMYADMIN.

  • Anzitutto dovete crearvi tanti forum su Drupal, quanti ne avete già sul VBULLETTIN.
  • In seconda analisi andremo a migrarci tutti gli utenti del VB su DRUPAL, così da mantenere gli autori dei vari posts. Per farlo dovremo entrare in PHYMYADMIN e crearci una nuova tabella copia di drp_users (drp_users2, dove drp è il suffisso) che contiene gli utenti di drupal.
CREATE TABLE `drp_users2` (
  `uid` int(10) unsigned NOT NULL default '0',
  `name` varchar(60) NOT NULL default '',
  `pass` varchar(32) NOT NULL default '',
  `mail` varchar(64) default '',
  `mode` tinyint(4) NOT NULL default '0',
  `sort` tinyint(4) default '0',
  `threshold` tinyint(4) default '0',
  `theme` varchar(255) NOT NULL default '',
  `signature` varchar(255) NOT NULL default '',
  `created` int(11) NOT NULL default '0',
  `access` int(11) NOT NULL default '0',
  `login` int(11) NOT NULL default '0',
  `status` tinyint(4) NOT NULL default '0',
  `timezone` varchar(8) default NULL,
  `language` varchar(12) NOT NULL default '',
  `picture` varchar(255) NOT NULL default '',
  `init` varchar(64) default '',
  `data` longtext,
  `userid` int(10) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  • Ammesso (e non concesso) che la tabella degli utenti VB si trovi sullo stesso DataBase di Drupal, provvederemo a copiarci da essa, attraverso una insert, i campi utili alla creazione dei nuovi utenti.
INSERT INTO `drp_users2` (`uid`, `name`, `pass`, 
`mail`, `mode`, `sort`, 
`threshold`, `theme`, `signature`, 
`created`, `access`, `login`, 
`status`, `timezone`, `language`, 
`picture`, `init`, `data`, `userid` )
SELECT @rownum:=@rownum+1 rownum, 
t.username, '[password criptata di drupal]', 
t.email, 0, 0, 
0, '', '', 
1176283461, 1180726137, 1180726137, 
1, '7200', 'it', 
'', t.email, 'a:8:{s:7:"contact";i:1;s:14:"picture_delete";s:0:"";s:14:"picture_upload";s:0:"";s:5:"block";a:1:{s:4:"blog";a:1:{i:0;i:0;}}s:11:"newsletters";a:13:{i:221;i:0;i:233;i:0;i:240;i:0;i:251;i:0;i:256;i:0;i:254;i:0;i:257;i:0;i:255;i:0;i:225;i:0;i:232;i:0;i:278;i:0;i:248;i:0;i:252;i:0;}s:16:"privatemsg_allow";i:1;s:28:"privatemsg_setmessage_notify";i:1;s:20:"privatemsg_mailalert";s:1:"0";}', userid
FROM (SELECT @rownum:=0) r, user t 
  • A questo punto, dopo aver fatto una count(*) dalla tabella degli utenti di DRUPAL, dovremo shiftare gli uid della nuova tabella drp_users2.
update drp_users2 set uid=uid+(select count(uid) from drp_users);
  • Ora aggiungiamo alla tabella originaria di drupal un campo "userid int(10)" e poi copiamoci dentro gli utenti del vecchio VB
INSERT INTO `drp_users` (`uid`, `name`, `pass`, 
`mail`, `mode`, `sort`, 
`threshold`, `theme`, `signature`, 
`created`, `access`, `login`, 
`status`, `timezone`, `language`, 
`picture`, `init`, `data`, `userid` )
SELECT `uid`, `name`, `pass`, 
`mail`, `mode`, `sort`, 
`threshold`, `theme`, `signature`, 
`created`, `access`, `login`, 
`status`, `timezone`, `language`, 
`picture`, `init`, `data`, `userid` 
from drp_users2;
  • Ora poichè i post del VBULLETTIN sono tutti stato formattati con BBcode, bisognerà caricarsi l'omonimo modulo su Drupal [1]. Una volta caricato ricordiamoci di aggiungere un Filtro di Input su Drupal, con il formato BBcode. Fatto? Benissimo, andiamo ora a vedere sulla tabella FILTER_FORMATS di Drupal, qual'è il codice formato assegnato (nel mio caso è 4).
  • Ok adesso prepariamoci al momento fatidico!! Siamo pronti per migrare un forum da VB a Drupal!! Segnamoci da una parte il codice del forum VB da Migrare ($forumid), il codice del forum Drupal in cui vogliamo trasferire i post ($tid) ed il codice del formato BBcode appena installato ($formatoBBcode).
  • Ora creiamo un file import_forum.php come di seguito...inchiodanto i suddetti parametri.
<?php
   
$dbhost = "xxxxx";
$dbuname = "xxxxxxx";
$dbpass = "xxxxxx";
$dbname = "xxxxxxxx";

$forumid=37;
$tid=20;
$formatoBBcode=4;

	$conn = mysql_connect($dbhost, $dbuname, $dbpass) or die("Connessione non riuscita: " . mysql_error());
  mysql_select_db($dbname, $conn) or die("Selezione DB non riuscita: " . mysql_error());


	$sql="SELECT threadid, title, forumid, postuserid from thread where forumid=$forumid";
	$result = mysql_query($sql);
	while ($row=mysql_fetch_array($result))
	{	

	$threadid = $row['threadid'];
	$title=$row['title'];	
        $title=str_replace("'", "\'", $title);
	$uid_old=$row['postuserid'];

//inserisco il nodo
$vid        = mysql_result(mysql_query("SELECT MAX(nid)+1 FROM drp_node"),0,0);
$uid        = mysql_result(mysql_query("SELECT uid from drp_users WHERE userid=$uid_old"),0,0);
$nid=$vid;

$sql_insert = "INSERT INTO `drp_node` (`nid`, `vid`, `type`, `title`, `uid`, `status`, `created`, `changed`, `comment`, `promote`, `moderate`, `sticky`) VALUES ($nid, $vid, 'forum', '$title', $uid, 1, 1180971453, 1180971453, 2, 0, 0, 0);";
echo $sql_insert.'<br>';
$result_ins= mysql_query($sql_insert);
//$nid = mysql_result(mysql_query("SELECT LAST_INSERT_ID()"),0,0);

//inserisco nel forum
$sql_insert1="INSERT INTO `drp_forum` (`nid`, `vid`, `tid`) VALUES ($nid, $vid, $tid);";
$result_ins1= mysql_query($sql_insert1);
echo $sql_insert1.'<br>';                

$sql_insert3="INSERT INTO `drp_term_node` (`nid`, `tid`) VALUES ($nid,$tid);";
$result_ins3= mysql_query($sql_insert3);
echo $sql_insert3.'<br>';                

$sql_insert4="INSERT INTO `drp_node_access` (`nid`, `gid`, `realm`, `grant_view`, `grant_update`, `grant_delete`) VALUES 
($nid, 1, 'term_access', 1, 0, 0),
($nid, 2, 'term_access', 1, 0, 0),
($nid, 3, 'term_access', 1, 0, 0),
($nid, 4, 'term_access', 1, 0, 0);";
$result_ins4= mysql_query($sql_insert4);
echo $sql_insert4.'<br>';                

$num_comments=mysql_result(mysql_query("SELECT count(*) from post where threadid=$threadid"),0,0);
$num_comments=$num_comments-1;

$sql_insert5="INSERT INTO `drp_node_comment_statistics` (`nid`, `last_comment_timestamp`, `last_comment_name`, `last_comment_uid`, `comment_count`) VALUES ($nid, 1181500797, NULL, $uid, $num_comments);";
$result_ins5= mysql_query($sql_insert5);
echo $sql_insert5.'<br>';  

		$livello = '01';
		$conta   = 1;
		$sql1="SELECT postid, title, pagetext, userid, parentid, dateline from post where threadid=$threadid order by postid, parentid";
		$result1 = mysql_query($sql1);
		while ($row1=mysql_fetch_array($result1))
		{
		//	echo '('.$threadid.')--> '.$row1['postid'].' '.$row1['title'].' '.$row1['pagetext'].' ['.$row1['userid'].'] <br>';			

$parentid = $row1['parentid'];
$date = $row1['dateline'];
$userid = $row1['userid'];
$uid_comment = mysql_result(mysql_query("SELECT uid from drp_users WHERE userid=$userid"),0,0);

$title = $row1['title'];
$title=str_replace("'", "\'", $title);
$body = $row1['pagetext'];
$body=str_replace("'", "\'", $body);

if ($parentid==0){
$sql_insert2= "INSERT INTO `drp_node_revisions` (`nid`, `vid`, `uid`, `title`, `body`, `teaser`, `log`, `timestamp`, `format`) VALUES ($nid, $vid, $uid_comment, '$title', '$body', '$title', '', 1180971453, $formatoBBcode);";
$result_ins2= mysql_query($sql_insert2);
echo $sql_insert2.'<br>';

}else{
$nome = mysql_result(mysql_query("SELECT name from drp_users WHERE userid=$userid"),0,0);

if ($conta==1){
$pid=0;
}else{
//$pid = mysql_result(mysql_query("SELECT MAX(cid) FROM drp_comments"),0,0);
$pid = mysql_result(mysql_query("SELECT LAST_INSERT_ID()"),0,0);
}
$conta = $conta+1;

$livello = $livello.'.00';
$sql_insert2= "INSERT INTO `drp_comments` (`pid`, `nid`, `uid`, `subject`, `comment`, `hostname`, `timestamp`, `score`, `status`, `format`, `thread`, `users`, `name`, `mail`, `homepage`) VALUES ($pid, $nid, $uid_comment, '$title', '$body', '0.0.0.0', 1180747076, 0, 0, $formatoBBcode, '$livello/', 'a:1:{i:0;i:0;}', '$nome', '', '');";
$result_ins2= mysql_query($sql_insert2);
echo $sql_insert2.'<br>';
}
		}


        echo '-----------------<br>';
	}				
								
	mysql_close($conn);
	  
?>			
				
  • Ora trasferiamo il file sul server e carichiamolo....
  • Ok ora il vostro forum è stato trasferito, dobbiamo fare un'ultima cosa: aggionrnare la tabella delle sequences di Drupal. Colleghiamoci ancora una volta con PHPMYADMIN al nostro DB e facciamo le seguenti updates.
UPDATE `drp_sequences` SET ID=(SELECT MAX(UID)+1 FROM DRP_USERS) WHERE NAME='drp_users_uid';
UPDATE `drp_sequences` SET ID=(SELECT MAX(NID)+1 FROM DRP_NODE) WHERE NAME='drp_node_nid';
UPDATE `drp_sequences` SET ID=(SELECT MAX(NID)+1 FROM drp_node_revisions) WHERE NAME='drp_node_revisions_vid';
UPDATE `drp_sequences` SET ID=(SELECT MAX(CID)+1 FROM drp_comments) WHERE NAME='drp_comments_cid';
  • Se avete seguito bene la guida, ora dovreste aver trasferito tutti i posts di un forum VB su un forum Drupal. Proseguite l'operazione per ogni Forum....(scusate se è un po' macchinoso come processo, ma l'ho fatto nel tempo libero e di notte!)

Ciao!

Tarabas

Come imposto gli Avatar sul Forum di Drupal?

Per far comparire gli Avatar a fianco dei Commenti o dei Contenuti è sufficiente impostare qualche opzione nella pagina di Amministrazione del Tema (Amministra->Struttura del Sito->Tema), in particolare sulle Impostazioni Generali.

Immagine:temi_admin.JPG

Nell'esempio in questione abbiamo impostato la visulizzazione dell'avatar sul Blog e sul Forum. Ok, ma se volessimo che l'immagine apparisse solo sul Forum e non sul Blog? Basterrebbe spuntare l'opzione del Blog et voilà...sul Blog non abbiamo piu' la data e l'utente che ha scritto il blog... Bella rogna è?

A questo punto dovremmo trovare il modo di poter pubblicare l'immagine sul Forum indipendentemente se è stata spuntata l'opzione "Ritratto dell'utente nei contenuti", come fare??

Semplicissimo!! Impostiamo la pagina di Amministrazione del Tema come segue, cioè specificando che vogliamo l'immagine solo sui Commenti.

Immagine:temi_admin1.JPG

Successivamente andiamo a modificare la pagina che gestisce il NODO sulla nostra template preferita. Ad esempio per il tema GARLAND la pagina è "/drupal/themes/garland/node.tpl.php".

Qui troveremo un codice di questo tipo, che specifica di visualizzare l'avatar solo se abilitato da template

    <?php if ($picture) {
      print $picture;
    }?>

Sotto a questo codice inseriamo il nostro...

<?php
// Only display this block when the user is browsing a forum topic:
    if (arg(0) == 'node' && is_numeric(arg(1))) {
      $node = node_load(arg(1));
      if (!empty($node) && $node->type == 'forum') {
          
         print theme('user_picture',$node);
      }
    }    
?>   

Questo permetterà di visualizzare l'immagine, a prescindere se sia stata specificata o meno sulla template, se il nodo in questione è un forum.

Ciao e alla prossima. Tarabas


Bug Fix: Download dei files con Private Method

In Drupal esistono 2 modi per scaricare i files:

  • Pubblico (poco sicuro): i files vengono scaricati direttamente dal file server (Es. http://www.miosito.com/files/pippo.zip), pertanto, non è possibile avere un controllo completo ed a meno non si utilizzi un sistema tipo htaccess, chiunque può scaricare i files.
  • Privato (sicuro): i files vengono scaricati attraverso drupal, pertanto è possibile tracciare i download ed avere un maggior controllo.

E' dunque preferibile usare il secondo metodo, ma su Drupal questo ha un mare di bugs.

Uno di questi è un simpatico comportamento che avviene quando si scarica un file: durante il download i files vengono rinominati senza motivo

Example:

File upload = ubuntu.rar

File download = x3n4xt4us

Dopo circa 3 ore di debugging ho capito perchè: l'HEADER non veniva passato correttamente.

In altre parole, quando proviamo a scaricare un file via PHP, dobbiamo specificare un po' di informazioni, contenute nell'header:

Ad esempio se volessimo scaricare il file "pippo.zip" di 11kb, dovremmo creare un codice di questo tipo.

<?php
header("Content-type: Application/octet-stream");
header("Content-Disposition: attachment; filename=pippo.zip");
header("Content-Description: Download PHP");
header("Content-Length: 11000");
readfile($nome_file);
?>

In Drupal il problema era che mancava questa parte "Content-Disposition: attachment; filename=....", per cui i files venivano rinominati a caxxo di cane.

Per risolvere il problema, bisogna patchare tutti i files/moduli che riguardano il download dei files.

Speriamo che ne tengano conto per il futuro...


Eccovi un elenco delle modifiche da apportare.

Ciao!!


-------------------------
Module: UPLOAD
File:   upload.module
--------------------------

function upload_file_download($file) {
  $file = file_create_path($file);
  $result = db_query("SELECT f.* FROM {files} f WHERE filepath = '%s'", $file);
  if ($file = db_fetch_object($result)) {
    if (user_access('view uploaded files')) {
      $node = node_load($file->nid);
      if (node_access('view', $node)) {
        $type = mime_header_encode($file->filemime);
        $filename = str_replace(" ","_",$file->filename);
        return array(
          'Content-Type: '. $type,
//tarabas: add filename to header
          'Content-Disposition: attachment; filename='.$filename,
          'Content-Length: '. $file->filesize,
        );
      }
      else {
        return -1;
      }
    }
    else {
      return -1;
    }
  }
}

--------------------------------------
MODULE: project_issue
FILE:   project_issue.module
--------------------------------------

function project_issue_file_download($file) {
  $file = file_create_path($file);
//tarabas: add filename to header
$file_info = db_fetch_object(db_query("SELECT nid, file_path, file_mime, file_size FROM {project_issues} WHERE file_path = '%s'", $file));
  if (!$file_info) {
//tarabas: add filename to header
$file_info = db_fetch_object(db_query("SELECT nid, file_path, file_mime, file_size FROM {project_comments} WHERE file_path = '%s'", $file));
  }
  if ($file_info) {
    if (user_access('access project issues')) {
      $node = node_load($file_info->nid);
      if (node_access('view', $node)) {
        $type = mime_header_encode($file_info->file_mime);
        $filename = str_replace(" ","_",basename($file_info->file_path));
        return array(
          'Content-type: '. $type,
//tarabas: add filename to header
          'Content-Disposition: attachment; filename='.$filename,
          'Content-length: '. $file_info->file_size,
        );
      }
      else {
         return -1;
      }
    }
    else {
      return -1;
    }
  }
}

----------------------------
Module: comment_upload
File:   comment_upload.module
-----------------------------

function comment_upload_file_download($file) {
  $file = file_create_path($file);
  $result = db_query("SELECT f.* FROM {comment_upload_files} f WHERE filepath = '%s'", $file);
  if ($file = db_fetch_object($result)) {
    if (user_access('view uploaded files')) {
      $node = node_load($file->nid);
      if (node_access('view', $node)) {
        $name = mime_header_encode($file->filename);
        $type = mime_header_encode($file->filemime);
        $filename = str_replace(" ","_",$file->filename);
        return array(
          'Content-Type: '. $type .'; name='. $name,
//tarabas: add filename to header
          'Content-Disposition: attachment; filename='.$filename,
          'Content-Length: '. $file->filesize,
          'Expires: 0', 'Pragma: cache', 'Cache-Control: private',
        );
      }
      else {
        return -1;
      }
    }
    else {
      return -1;
    }
  }
}

Ps. English version: http://drupal.org/node/155594

Bug Fix: Book Module: inserimento e modifica pagine all'interno del proprio book

Ogni volta che un utente va a modificare o inserire pagine del book, c'è la possibilità che queste pagine vengano inserite in altri books. Questo snippet permette di evitare il problema. Ciao

-------------------------
Module: BOOK
File:   book.module
--------------------------

/**
 * Returns an array of titles and nid entries of book pages in table of contents order.
 */
function book_toc($exclude = 0) {
  $result = db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 ORDER BY b.weight, n.title'));

  $children = array();
  while ($node = db_fetch_object($result)) { 
      if (!$children[$node->parent]) {
        $children[$node->parent] = array();
      }      
      $children[$node->parent][] = $node;
  }

  $toc = array();
  // If the user has permission to create new books, add the top-level book page to the menu;
  if (user_access('create new books')) {
    $toc[0] = '<'. t('top-level') .'>';
  }

  $toc = book_toc_recurse(0, '', $toc, $children, $exclude);

//---------------------------------------
  //tarabas 10/04/2008: the normal user browse just his own book
  if (!user_access('create new books')){
    $toc = book_browse_current($toc);
  }
//---------------------------------------

  return $toc;
}

/**
 * tarabas 10/04/2008
 * Returns an array of titles and nid entries of current book pages in table of contents order.
 */
function book_browse_current($toc) {
  $parent=NULL;
  $nid   =NULL;
  if (!is_null(arg(4)) && is_numeric(arg(4))){
     $parent=arg(4);  
  }else {
    if (!is_null(arg(1)) && is_numeric(arg(1))){
      $nid=arg(1);
      //cerco il padre...
      //questi sono i noti root dei books
      $result = db_query('SELECT parent FROM {book} WHERE nid=%d',$nid);
      while ($rows = db_fetch_object($result)) {
        //drupal_set_message('Nodo Padre='.$rows->parent,'messages'); 
        $parent = $rows->parent;
      }
    }
  }
//questi sono i noti root dei books
  $result = db_query('SELECT nid FROM {book} WHERE parent=0');
  $book_root=array();
  while ($node = db_fetch_object($result)) {
    $book_root[] = $node->nid;
  }
  $trovato   = FALSE;
  //scorro l'array
  $my_book   = array(); 
  //scorro l'array albero dei book
  foreach ($toc as $key => $value) {
    //drupal_set_message($key.'-->'.$value,'messages');
    //se il nodo è uno tra quelli base
    if (in_array($key,$book_root)){       
       //se non ho già trovato l'elemnto nell'albero
       if ($trovato){
           break;
       }
       //inizializzo il nuovo albero
       $my_book = array();        
    }
    //creo un albero parallelo
    $my_book[$key] = $value;
    if (($key==$parent) && !is_null($parent)){
       $trovato=TRUE;
       //drupal_set_message('ENTRATO'.$key.'=='.$parent,'messages');      
     }
   }
  if (!$trovato){
     $my_book = $toc;
  }
  return $my_book;
}
//-------------------------------------------------------------------------------


wizard linux team