Drupal Hacking
Da Wizard linux team wiki.
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.
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.
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;
}
//-------------------------------------------------------------------------------

