2. 30/05/2013 (c) francescobrunetta.it 2
Antefatto
www.unijuris.it
Osservatorio sulla giurisprudenza fallimentare
Sito nato nel 2009
Sviluppato con Drupal 5
3. 30/05/2013 (c) francescobrunetta.it 3
Antefatto
Sito complesso con:
Funzioni di catalogazione provvedimenti Tribunali
(Sentenze) – multi vocabolario – allegati – data
riferimento
Altre strutture informative (approfondimenti,
notizie, info didattiche, ecc.)
Funzioni di ricerca: per tassonomia, per parola
chiave, per data
Filtraggio per tassonomia
Newsletter con iscrizione anonimi
4. 30/05/2013 (c) francescobrunetta.it 4
Antefatto
Ospitato su macchina virtuale (Aruba)
Modificato nel tempo per soddisfare diverse
esigenze
Di conseguenza, alcune scelte tecnologiche
si sono modificate nel tempo
iniziale uso di “tag cloud” poi non più necessario
tassonomie e tipi di contenuto variati nel tempo
5. 30/05/2013 (c) francescobrunetta.it 5
Perché una migrazione
Sito molto vecchio:
Drupal 5 – non più supportato
Uso di versione PHP obsoleta
Rischi per la sicurezza
Limitate funzionalità
Impossibile aggiungere nuove funzionalità
Hosting limitato
Poco spazio disco
Difficile gestione e aggiornamento sw di base
6. 30/05/2013 (c) francescobrunetta.it 6
Requisiti nuovo sito
Rispettare funzionalità esistenti
(catalogazione, ricerca, strumenti)
Riportare allegati (file pdf anche multipli
allegati a molti documenti)
Aggiungere funzionalità alla ricerca per
parole chiave
Aggiungere altre funzionalità non previste:
Vendite competitive gestite dal pubblicatore
Dati aggiuntivi (altre categorie, nr. sentenza,
ecc…)
7. 30/05/2013 (c) francescobrunetta.it 7
Criticità (1)
Impossibile una migrazione tout court da
Drupal 5 a Drupal 7
salto troppo grande: troppi cambiamenti nel core
alcuni moduli usati non servono più (tag clouds,
ecc.). Altri non esistono per D7.
Scelta obbligata:
Realizzare nuovo sito con corretta struttura
Reimportare i dati
8. 30/05/2013 (c) francescobrunetta.it 8
Criticità (2)
Numero di documenti da migrare:
relativamente elevato (circa 2000)
Improbabile migrazione “manuale” uno per uno
Necessario mantenere indirizzi originali già
registrati su motori di ricerca
www.unijuris.it/node/xxx
Taxonomy/term/xxxx
Mai implementato un meccanismo di autoalias
Necessario non perdere informazioni su:
nome del pubblicatore; data di pubblicazione!
9. 30/05/2013 (c) francescobrunetta.it 9
Fasi dell’operazione
E’ stato necessario lungo lavoro di analisi e
messa a punto per la migrazione
Una prima fase di sperimentazione (su:
strumenti per l’indicizzazione e la ricerca;
strumenti per la migrazione dei dati)
Una seconda fase (Unijuris 2 Reloaded!) con
creazione ex-novo del sito e migrazione
effettiva dei contenuti
10. 30/05/2013 (c) francescobrunetta.it 10
Prima fase: sperimentazione
Creati tipi di contenuto necessari (Sentenze,
Pagine informative)
Creati vocabolari e importati i termini con
modulo: taxonomy_manager
Primo problema: non consente di importare i TID
i termini hanno un nuovo numero non va
bene
Creati nodi “dummy” per sperimentazione
11. 30/05/2013 (c) francescobrunetta.it 11
Prima fase: sperimentazione (2)
Effettuato sperimentazione con:
ricerca “core search”;
ricerca con “search api”;
strumenti di filtraggio “facets api”, applicati al core
search e a search api
Modulo “taxonomy filter” (ancora in versione -dev
ma necessario per mantenere funzionalità pre-
esistenti)
12. 30/05/2013 (c) francescobrunetta.it 12
Prima fase: sperimentazione (3)
Strumenti di importazione vari
La scelta finale per l’importazione è stata:
Feeds http://drupal.org/project/feeds
Feeds tamper
http://drupal.org/project/feeds_tamper
Vantaggi:
Molto elastico
Consente di conservare informazioni di base (nid,
tid, uid, autore….. Tutti gli id!)
13. 30/05/2013 (c) francescobrunetta.it 13
Feeds e Feeds Tamper
Modulo Feeds consente importazione di dati
da varie fonti: incluso http e file .csv
Si creano diversi “importer”, associati a content
type specifici;
Si mappano i campi del file .csv con i campi del
content type opportuno con qualche
accorgimento!
Si importano effettivamente i dati
14. 30/05/2013 (c) francescobrunetta.it 14
Feeds e Feeds Tamper
Modulo Feeds_tamper consente di trattare
ogni singolo campo del file .csv PRIMA
dell’importazione. Ad es:
Conversioni formati data
Trim
Explode
Molte altre possibilità già pronte
15. 30/05/2013 (c) francescobrunetta.it 15
Seconda fase: Unijuris 2 Reloaded!
Finite le sperimentazioni, è stato necessario
ricreare sito da zero con:
Tipi di contenuto completi (come in prima fase)
NIENTE vocabolari, niente termini
Conservato il vocabolario 1 tags
NB: VID 1 non era usato sul sito “sorgente”
Ruoli e permessi
Niente utenti
16. 30/05/2013 (c) francescobrunetta.it 16
Unijuris2 reloaded: importare tassonomia
Problema: nessun modulo trovato consente
di importare categorie rispettando i tid tutti
li creano ex-novo
Soluzione adottata: sporca ma funzionante
Descritta in:
http://drupal.org/node/1728672
Funziona! Niente effetti collaterali
17. 30/05/2013 (c) francescobrunetta.it 17
Unijuris2 reloaded: importare tassonomia
In sintesi:
Accesso al db (usato phpmyadmin)
Copiato db “sorgente” su stesso MySql server che
ospita sito “target”
Annotato (a mano) il VID (vocabulary id) di ogni
vocabolario
Importazione “manuale” via comando SQL
18. 30/05/2013 (c) francescobrunetta.it 18
Esempio: per vocabolario con vid 2:
INSERT INTO `db7target`.taxonomy_vocabulary
SELECT vid,name, LOWER(name),
description,hierarchy,module,weight
FROM `db5-source`.vocabulary v where v.vid =
2
Unijuris2 reloaded: importare vocabolari
19. 30/05/2013 (c) francescobrunetta.it 19
Esempio: per vocabolario con vid 2:
INSERT INTO `db7target`.taxonomy_term_data
(tid,vid,name,description,weight)
SELECT tid,vid,name,description,weight
FROM `db5-source`.term_data td WHERE td.vid = 2
INSERT into `db7target`.taxonomy_term_hierarchy
SELECT t.*
FROM `db5-source`.term_hierarchy t
JOIN `db5-source`.term_data td on td.tid = t.tid
where td.vid = 2
It works like a charm!
Unijuris2 reloaded: importare termini
20. 30/05/2013 (c) francescobrunetta.it 20
Feeds consente di importare utenti
Ma non abbiamo provato
Nel nostro caso, pochi utenti ricreati a
mano (più rapido)
Importante: usare stesso indirizzo email degli
utenti originali!
Verificare ruoli e permessi
Unijuris2 reloaded: importare utenti
21. 30/05/2013 (c) francescobrunetta.it 21
Unijuris2 reloaded: importare nodi
Procedura seguita:
Creare nuovi content type sul sito “target” (con tutti i campi
necessari, inclusi riferimenti tassonomia)
Esportare nodi “originali” su file CSV
Importare CSV con importer del modulo FEEDS
Obbiettivi generali:
Ottenere il CSV dal sito originale
Rispettare HTML dei “body”
Rispettare tassonomia
Rispettare autori e date di creazione
Importare attachment (anche multipli)
22. 30/05/2013 (c) francescobrunetta.it 22
Meglio: esportazione/importazione separate
Una per ogni tipo di contenuto
Ad es:
Prima esportato/importato sentenze
Poi “pagine informative”
Poi “newsletter”
Ecc
Unijuris2 reloaded: importare nodi
23. 30/05/2013 (c) francescobrunetta.it 23
Primo problema: ottenere CSV (su Drupal 5)
Usato:
https://drupal.org/project/views_bonus (per D5)
Views esportazione su CSV dei field opportuni
Funziona ma con qualche problema!
Esportare i nodi da Drupal 5 (1)
24. 30/05/2013 (c) francescobrunetta.it 24
Esportare i nodi da Drupal 5 (2)
Per ogni esportazione create TRE views
diverse (3 views diverse per ogni content
type diverso)
1) tutti i campi necessari MENO body e
attachment
2) solo NID + BODY
3) solo NID + FILEPATH
Importazione nodi in tre fasi!
Ora vediamo perché!
26. 30/05/2013 (c) francescobrunetta.it 26
Importare nodi fase 1
Importazione dei nodi SENZA body e SENZA
allegati
Procedura:
Esportare su CSV da sito sorgente
Predisporre importazione su sito target
Importare creazione automatica dei nodi con
NID originale e TIDs originali
27. 30/05/2013 (c) francescobrunetta.it 27
Fase 1.1 – Esportazione
Prima views: esportato (su .csv):
Nid
Titolo
Created time (as short date)
User-email (dell’autore del documento)
Taxonomy terms, uno per ogni vocabolario
utilizzato
Tutti gli altri campi
Ordine: Node ID ASCENDING
28. 30/05/2013 (c) francescobrunetta.it 28
Fase 1.2 – Preparazione target
Sul sito “target”
nel tipo contenuto: I campi dei term reference
devono essere AUTOCOMPLETE!!!
Creato importer con modulo feed; mappando NID
Id del nodo (UNIQUE), createdPublished
date; emailuser email; termini tassonomia nei
corrispondenti campi; ecc.
NON BASTA!
29. 30/05/2013 (c) francescobrunetta.it 29
Nel .csv i termini di tassonomia sono separati
da “ | “:
"93", "xxxx","concordato | classi | transazione"
Necessario “esplodere” la stringa in un array
Si fa con: feeds tamper explode separatore
“ | “ (notare spazio prima e dopo |)
Uno per ogni campo term reference!
Fase 1.3 – Preparazione target
30. 30/05/2013 (c) francescobrunetta.it 30
Importare i nodi dal csv:
I nodi vengono creati con lo stesso NID del sito
originale (sono sicuramente univoci)
L’email viene usata per associare l’autore
(funziona!)
I termini vengono associati correttamente (in base
al nome grazie ad autocomplete!) con stesso TID
del sito originale!
Abbiamo avuto qualche problema con data di
creazione (vedremo dopo!)
Fase 1.4 – Importazione
32. 30/05/2013 (c) francescobrunetta.it 32
Importare nodi fase 2
Aggiornamento dei nodi con inserimento dei
BODY completi di tags html
Procedura:
Esportare su CSV da sito sorgente (attenti!)
Predisporre importazione su sito target
Post-processing dei files csv!
Importare aggiornamento automatico dei nodi
con inserimento del body
33. 30/05/2013 (c) francescobrunetta.it 33
Fase 2.1 – Esportazione
Seconda views: esportato (su .csv):
Nid
Body
Ordine: Node ID ASCENDING
34. 30/05/2013 (c) francescobrunetta.it 34
Problema: l’esportazione del body su csv
NON riporta i tag html originali male, ci
servono!
Trucco: sul sito sorgente, piccola patch a
sitesallmodulesviews_bonusviews_bonus_export
.module (linea 210)
- $values[] = '"' . str_replace('"', '""',
decode_entities(strip_tags($value))) . '"';
+ $values[] = '"' . str_replace('"', '""',
decode_entities($value)) . '"';
Fase 2.2 – Esportazione
35. 30/05/2013 (c) francescobrunetta.it 35
Fase 2.3 – Esportazione
Da usare SOLO per esportazione body:
Si modifica il file views_bonus_export.module
Si esportano i dati con la view
Si ripristina views_bonus_export.module originale
Si ottiene Body con tutti i tag html originali!
36. 30/05/2013 (c) francescobrunetta.it 36
Secondo problema: Drupal 5 nel csv
aggiunge al body informazioni inutili!
Ad esempio: aggiunge una tabella in HTML con
gli attachment!!
<table id=""attachments"">
<thead><tr><th>Allegato</th><th>Dimensione</th>
</tr></thead><tbody> <tr class=""odd""><td><a
href=""http://www.unijuris.it/files/giuris/esdebitazione
21.12.2007 Trib. Udine.pdf"">esdebitazione 21.12.2007 Trib.
Udine.pdf</a></td><td>46.15 KB</td> </tr></tbody></table>
Fase 2.4 – trattare il file csv
37. 30/05/2013 (c) francescobrunetta.it 37
Soluzione: uno script che legge il .csv
originale ed elimina testo inutile
Noi usato: uno script php (altri linguaggi
andavano anche bene)
Fase 2.5 – trattare il file csv
38. 30/05/2013 (c) francescobrunetta.it 38
<?php
$myFile = "20130528-003-SENTENZE-body.csv";
$count = 0;
$cisiamo = false;
$file = fopen($myFile, 'r');
$primalinea = fgets($file);
echo $primalinea;
while(!feof($file))
{
$linea = fgets($file);
if ($linea == "<table id=""attachments"">n") {
$cisiamo = true;
}
if ($cisiamo) {
if ($linea == "</table>n") {
$cisiamo = false;
$linea = fgets($file);
}
}
if (!$cisiamo) { echo $linea;}
}
fclose($file);
?>
Legge il file riga per
riga
Riscrive in output
tutto meno la
tabella “inutile”
Abbiamo un nuovo
file “pulito”
Fase 2.6 – trattare il file csv
39. 30/05/2013 (c) francescobrunetta.it 39
Simile problema con altre informazioni
“intruse”:
<div class=""field field-type-date field-field-
data""><div class=""field-items""><div class=""field-
item""><div class=""field-label-inline-first"">Data di
riferimento: </div><span class=""date-display-
single"">30/09/2006</span></div></div></div>
Risolto con altrettanti script
NB: c’era una soluzione più elegante ma ce
ne siamo accorti dopo!
Fase 2.7 – trattare il file csv
40. 30/05/2013 (c) francescobrunetta.it 40
Fase 2.8 – importazione
Creato nuovo importer con modulo Feed:
Per AGGIORNARE i nodi
Usando NID come campo univoco
Inserendo BODY
Ha funzionato bene!
Nodi esistenti aggiornati con aggiunta di “body”
completo di tags html
NID originari ancora preservati!
42. 30/05/2013 (c) francescobrunetta.it 42
Importare nodi fase 3
Aggiornamento dei nodi con aggiunta degli
Allegati originali!
Procedura:
Esportare su CSV da sito sorgente
Predisporre importazione su sito target
Copia dei files originali
Post-processing dei files csv!
Importare aggiornamento automatico dei nodi
con creazione dei file allegati!
43. 30/05/2013 (c) francescobrunetta.it 43
Fase 3.1 – Esportazione
Terza views: esportato (su .csv):
Nid
File Path
Ordine: Node ID ASCENDING
44. 30/05/2013 (c) francescobrunetta.it 44
Fase 3.2 – copia dei file
Copiato tutta la cartella “files” originale in una
cartella provvisoria su sito target
Ad esempio: private/fileoriginali
Attenzione ai nomi dei files
Su Unix sono case sensitive, su Windows no!
Si rischia di perdere file: su windows Pippo.pdf coincide
con PIPPO.pdf, su U*X sono file diversi!
Rispettare struttura di sottocartelle!
45. 30/05/2013 (c) francescobrunetta.it 45
Fase 3.3 – trattare il file csv
Primo problema: nel .csv c’è una riga per
ogni nodo e per ogni file allegato
Se un nodo non ha allegati, è elencato lo
stesso "194",""
Se un nodo ha più allegati, è elencato più
volte!
"194","files/giuris/primofile.pdf"
"194","files/giuris/secondofile.pdf"
46. 30/05/2013 (c) francescobrunetta.it 46
Fase 3.4 – trattare il file csv
Soluzione: trattare il file csv con (ennesimo)
script
Se un nodo ha più allegati, dev’essere
elencato una sola volta con allegati
concatenati (ad es. da “|”)
Poi useremo “tamper” per esplodere il nuovo
campo! (separatore: “|”)
"194","files/giuris/primofile.pdf|files/giuris/secondofile.pdf"
47. 30/05/2013 (c) francescobrunetta.it 47
Fase 3.5 – trattare il file csv
Altro problema: far capire al sito target DOVE
prendere i file
La sintassi corretta da usare nel file csv
dev’essere:
"194","private://fileoriginali/files/giuris/primofil
e.pdf|
private://fileoriginali/files/giuris/secondofile.p
df“
Lo script deve aggiungere anche questo!
48. 30/05/2013 (c) francescobrunetta.it 48
Fase 3.6 – importazione
Il content type deve prevedere campo “file”
con multiple occorrenze
Si consiglia cartella specifica per ogni tipo di
contenuto
Così teniamo d’occhio la situazione
dell’importazione!
49. 30/05/2013 (c) francescobrunetta.it 49
Fase 3.7 – importazione
Creato nuovo importer con modulo Feed:
Per AGGIORNARE i nodi
Usando NID come campo univoco
Mappando filepath campo allegati
Usando un tamper su filepath esplodi “|” (senza spazi!)
Ha funzionato bene!
Nodi esistenti aggiornati con aggiunta di file allegati anche
multipli
I file vengono prelevati dalla cartella
private/fileoriginali/files… e copiati nella cartella files target!
50. 30/05/2013 (c) francescobrunetta.it 50
Fase 3.8 – Considerazione
Si poteva fare tutto con una singola fase
(viewscsvtrattamentiimport) invece di
tre?
Probabilmente sì. Ma era più facile andare “per
passi”
51. 30/05/2013 (c) francescobrunetta.it 51
Un problema ulteriore: la data
Ce ne siamo accorti dopo
La data di creazione originale non veniva
rispettata!
Nodi importati avevano tutti la nuova data di
creazione! MALE
Perché?
52. 30/05/2013 (c) francescobrunetta.it 52
Un problema ulteriore: la data
Un banale problema di formato
Nel csv:
node_id,created
"6", "22/01/2008 - 16:39“
Il sito target si aspettava:
node_id,created
"6", "01/22/2008 16:39“
mm/dd invece di dd/mm – e spazio
separatore delle ore invece di “-”!
53. 30/05/2013 (c) francescobrunetta.it 53
Ancora uno script?
Soluzione banale era: piccolo script per
trattare il file
Ancora!
Ma c’e’ strada più elegante: aggiungere un
plugin a feeds_tamper!
Possibile creare plugin personalizzati
Basta creare un file .inc apposito
54. 30/05/2013 (c) francescobrunetta.it 54
I plugin di feeds_tamper
<?php
$plugin = array(
'form' => 'feeds_tamper_trattadata_form',
'callback' => 'feeds_tamper_trattadata_callback',
'name' => 'tratta la data come dico io',
'multi' => 'loop',
'category' => 'Date/time',
);
function feeds_tamper_trattadata_form($importer,
$element_key, $settings) {
$form = array();
$form['html'] = array(
'#markup' => t('rigira un po la data come piace a me'),
);
return $form;
}
function feeds_tamper_trattadata_callback($result, $item_key,
$element_key, &$field, $settings, $source) {
$data_ingresso = $field;
$rimpiazzata = str_replace(" - ","/",$data_ingresso);
$data_originale = explode("/",$rimpiazzata);
$data_nuova = $data_originale[1] . "/" .
$data_originale[0] . "/" .
$data_originale[2] . " " .
$data_originale[3];
$unixtime = strtotime($data_nuova);
$unixtime = $unixtime - 7200;
$field = date("m/d/Y H:i",$unixtime);
*/
}
Il plugin “trattadata”
feeds_tamper/plugin/tratadat
a.inc
Tratta la data come serviva a
noi
Anche correggendo problemi
di “timezone” sul sito
originale!
Basta applicare questo
“tamper” al primo importer e
ripetere l’importazione
Attenti, non è detto che serva
o funzioni in ogni situazione!
55. 30/05/2013 (c) francescobrunetta.it 55
Risultato finale
I nodi originali sono tutti sul sito nuovo
Gli indirizzi originali sono conservati:
node/xxx, taxonomy/term/xxx
Totale compatibilità col pre-esistente
Gli allegati sono associati ai giusti documenti
L’autore dei documenti è coerente, anche le
date!